绕过防盗链的几种方式

23 篇文章 1 订阅

需要进行防盗链的绕过,我们必须先要了解IframeRefererXMLHttpRequest对象的基本知识

目录

Iframe

基本用法

sandbox 属性

loading 属性

Referer

Referrer-policy

设置referrer的两种方法

下面举三个将referrer设置为no-referrer的例子:

首先是没有设置no-referrer的,即有referer

这里是referer1中使用方法1设置了no-referer

这里是referer1中使用方法2设置了no-referer

XMLHttpRequest

简介

盗链

防盗链的工作原理

为什么我们要绕过防盗链?

绕过防盗链的几种方式

利用HTTPS网站盗链http资源网站(HTTPS->HTTP)

利用在头部设置meta

利用referrerpolicy="no-referrer"

利用iframe伪造请求referer

利用XMLHttpRequest

利用fetch


Iframe

<iframe>标签用于在网页里面嵌入其他网页。

基本用法

<iframe>标签生成一个指定区域,在该区域中嵌入其他网页。它是一个容器元素,如果浏览器不支持<iframe>,就会显示内部的子元素。

<iframe src="https://www.example.com"
        width="100%" height="500" frameborder="0"
        allowfullscreen sandbox> //这里的sandbox可以保证安全
  <p><a href="https://www.example.com">点击打开嵌入页面</a></p>
</iframe>

上面的代码在当前网页嵌入https://www.example.com,显示区域的宽度是100%,高度是500像素。如果当前浏览器不支持<iframe>,则会显示一个链接,让用户点击。

浏览器普遍支持<iframe>,所以内部的子元素可以不写。

iframe的属性如下:

  • allowfullscreen:允许嵌入的网页全屏显示,需要全屏 API 的支持,请参考相关的 JavaScript 教程。

  • frameborder:是否绘制边框,0为不绘制,1为绘制(默认值)。建议尽量少用这个属性,而是在 CSS 里面设置样式。

  • src:嵌入的网页的 URL。

  • width:显示区域的宽度。

  • height:显示区域的高度。

  • sandbox:设置嵌入的网页的权限,详见下文。

  • importance:浏览器下载嵌入的网页的优先级,可以设置三个值。high表示高优先级,low表示低优先级,auto表示由浏览器自行决定。

  • name:内嵌窗口的名称,可以用于<a><form><base>target属性。

  • referrerpolicy:请求嵌入网页时,HTTP 请求的Referer字段的设置。参见<a>标签的介绍。

sandbox 属性

嵌入的网页默认具有正常权限,比如执行脚本、提交表单、弹出窗口等。如果嵌入的网页是其他网站的页面,你不了解对方会执行什么操作,因此就存在安全风险。

为了限制<iframe>的风险,HTML 提供了sandbox属性,允许设置嵌入的网页的权限,等同于提供了一个隔离层,即“沙箱”。

sandbox可以当作布尔属性使用,表示打开所有限制。

<iframe src="https://www.example.com" sandbox>
</iframe>

sandbox属性可以设置具体的值,表示逐项打开限制。未设置某一项,就表示不具有该权限。

以最小权限为原则

注意,不要同时设置allow-scriptsallow-same-origin属性,这将使得嵌入的网页可以改变或删除sandbox属性。

loading 属性

<iframe>指定的网页会立即加载,有时这不是希望的行为。

<iframe>滚动进入视口以后再加载,这样会比较节省带宽。

loading属性可以触发<iframe>网页的懒加载。

该属性可以取以下三个值:

  • auto:浏览器的默认行为,与不使用loading属性效果相同。

  • lazy<iframe>的懒加载,即将滚动进入视口时开始加载。

  • eager:立即加载资源,无论在页面上的位置如何。

<iframe src="https://example.com" loading="lazy"></iframe>

上面代码会启用<iframe>的懒加载。

有一点需要注意,如果<iframe>是隐藏的,则loading属性无效,将会立即加载。

Referer

一定程度上防御crsf(客户端请求伪造)

Referer请求包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面的链接进入的。

Referrer-policy

Referer-policy作用就是为了控制请求头部中的referer的内容包含了以下信息:

  • no-referer:整个referer首部会被移除,访问来源信息不随着请求一起发送。

  • no-referer-when-downgrade:在没有指定任何策略的情况下用户代理的默认行为。在同安全等级的情况下,发送文件的源为引用地址(HTTPS->HTTPS);在降级的情况下不会发送此首部(HTTPS->HTTP)

  • origin:在任何情况下,仅发送文件的源作为引用地址

  • orgin-when-cross-origin:对于同源的请求,会发送完整的URL作为引用地址,但是对于非同源请求仅仅发送文件的源

  • same-orgin:对于同源的请求会发送引用地址,但是对于非的同源请求则不发送引用地址信息。

  • strict-origin:在同等安全级别的情况下,发送文件的源作为引用地址(HTPPS->HTTPS),但是在降级的情况下不会发送(HTTPS->HTTP)

  • strict-origin-cross-origin,对于同源的请求,会发送完整的URL作为引用地址;在同安全等级的情况下,发送文件的源为引用地址(HTTPS->HTTPS);在降级的情况下不会发送此首部(HTTPS->HTTP)

  • unsafe-url:无论是同源请求还是非同源请求,都发送完整的URL(移除参数信息后)作为引用地址。(最不安全了)

设置referrer的两种方法

方法1:在html页面中的head标签中的meta中设置

<meta name="referer" content="no-referer">

方法2:在引入script的script标签的属性中设置referrerpolicy="no-referer"

下面举三个将referrer设置为no-referrer的例子:

首先是没有设置no-referrer的,即有referer

(1)首先编写referer1.html

<!DOCTYPE html>
<html lang="en">
​
<head>
    
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
​
<body>
    <!-- noreferer测试 -->
    <div>aaa</div>
</body>
​
</html>

这里并没有什么特别的,就是在页面中有一个div标签,其中写着aaa 

(2)编写referer2.html

<!DOCTYPE html>
<html lang="en">
​
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<h1>hello world</h1>
<a href="./referer1.html">123</a>
这里使用链接的形式访问test.html网页
<body>
</body>
​
</html>

这里使用a标签尝试将referer1.html插入到a标签中 

(3)测试

在浏览器的URL中访问referer2.html

这里是referer1中使用方法1设置了no-referer

在referer中增加这样一行:

    <meta name="referrer" content="no-referrer">

然后使用上面相同的方式查看是否有referer

 

可以看到,这里已经没有referer了

这里是referer1中使用方法2设置了no-referer

(1)修改referer1页面为:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="./test.js" Referrerpolicy="no-referrer">
    //这里使用no-referrer禁用referrer
    </script>
    <!-- noreferer测试 -->
    <div>aaa</div>
</body>

</html>

(2)然后我们新建一个名为test.js的文件

内容为:

alert(document.cookie);

(3)然后访问referer1.html

可以看到,没有referer,由于没有了referer我们也可以看到成功的弹窗了

XMLHttpRequest

简介

浏览器与服务器之间,采用 HTTP 协议通信。用户在浏览器地址栏键入一个网址,或者通过网页表单向服务器提交内容,这时浏览器就会向服务器发出 HTTP 请求。

XMLHttpRequest对象是 AJAX 的主要接口,用于浏览器与服务器之间的通信。尽管名字里面有XMLHttp,它实际上可以使用多种协议(比如fileftp),发送任何格式的数据(包括字符串和二进制)。

XMLHttpRequest本身是一个构造函数,可以使用new命令生成实例。它没有任何参数。

var xhr = new XMLHttpRequest();//即初始化时没有任何参数

一旦新建实例,就可以使用open()方法指定建立 HTTP 连接的一些细节。

xhr.open('GET', 'http://www.example.com/page.php', true);//open方法

上面代码指定使用 GET 方法,跟指定的服务器网址建立连接。

第三个参数true,表示请求是异步的。

然后,指定回调函数,监听通信状态(readyState属性)的变化。

xhr.onreadystatechange = handleStateChange; 
​
function handleStateChange() {
  // ...
}

上面代码中,一旦XMLHttpRequest实例的状态发生变化,就会调用监听函数handleStateChange

最后使用send()方法,实际发出请求。

xhr.send(null);

上面代码中,send()的参数为null,表示发送请求的时候,不带有数据体

如果发送的是 POST 请求,这里就需要指定数据体。

一旦拿到服务器返回的数据,AJAX 不会刷新整个网页,而是只更新网页里面的相关部分,从而不打断用户正在做的事情。

注意:AJAX 只能向同源网址(协议、域名、端口都相同)发出 HTTP 请求如果发出跨域请求,就会报错

盗链

盗链是指自己的页面上展示以下并不在自己服务器上的一些内容,获别人的资源地址,绕过别人的资源展示页面,直接在自己的页面上向最终用户提供此内容,一般被盗链的都是图片、可执行文件、音频文件、压缩文件等资源。

通过盗链的手段可以减轻自己服务器的负担。

防盗链的工作原理

通过referere或者签名,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以追踪到显示它网页地址,一旦检测到来源不是本站点,即进行阻止或者返回指定的页面

为什么我们要绕过防盗链?

因为通过referere或者签名,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以追踪到显示它网页地址,一旦检测到来源不是本站点,即进行阻止或者返回指定的页面

三种情况下允许引用图片:

  1. 本网站

  2. 无referer信息的情况下。(服务器认为从浏览器直接访问图片的图片的URL,所以这种情况下能正常访问)

  3. 授权的网址

我们可以在https的网页中用http请求另一个https网站的资源。

此时可以不发送我们的referer字段,达到绕过防盗链的效果(由于浏览器的升级,现在这种操作已经被禁止了)

实现原理:在访问图片时让其无referrer

绕过防盗链的几种方式

利用HTTPS网站盗链http资源网站(HTTPS->HTTP)

现在这种方式已经无法复现了

利用在头部设置meta

(1)首先在refrrer1文件中添加一行

    <img src="https://img-blog.csdnimg.cn/5ff039c8a8cd47c98e26d694854e8962.jpeg" alt="你这图有问题啊">

(2)尝试访问

很明显图片没有加载出来,因为csdn网站将发现我们的referer并不是一个合法的网站,不会让我们加载

(3)那么我们就可以在meta中设置no-referrer的方式来尝试

   <meta name="referrer" content="no-referrer">

(4)再次访问

成功访问

利用referrerpolicy="no-referrer"

注:这种方式就是在script添加这样

    <script src="这里是一个js页面" Referrerpolicy="no-referrer">

一句,呈现的效果和上面的meta一样,这里不再赘述

利用iframe伪造请求referer

内容参考:如何绕开referrer防盗链 - 掘金 (juejin.cn)

(1)修改referrer1.html

    <img src="https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF" alt="你这图有问题啊">

(2)编辑test.js

function showImg(src, wrapper) {
    let url = new URL(src);
    let frameid = 'frameimg' + Math.random();
    window.img = `<img id="tmpImg" width=400 src="${url}" alt="图片加载失败,请稍后再试"/> `;
​
    // 构造一个iframe
    iframe = document.createElement('iframe')
    iframe.id = frameid
    iframe.src = "javascript:parent.img;" // 通过内联的javascript,设置iframe的src
    // 校正iframe的尺寸,完整展示图片
    iframe.onload = function () {
        var img = iframe.contentDocument.getElementById("tmpImg")
        if (img) {
            iframe.height = img.height + 'px'
            iframe.width = img.width + 'px'
        }
    }
    iframe.width = 200
    iframe.height = 200
    iframe.scrolling = "no"
    iframe.frameBorder = "0"
    wrap.appendChild(iframe)
}
showImg('https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF', document.querySelector('#container'));
​

运行代码可以看见,通过这种方式也可以实现隐藏referer的功能,因此用作不支持referrerPolicy的一种替代方案。

在某些不支持javascript内联运行的场景下,这种方案也是不可行的,比如在chrome扩展程序,由于content_security_policy,使用内联JavaScript会报错

(3)测试

成功盗用!

利用XMLHttpRequest

XMLHttpRequest对象提供了setRequestHeader方法,用于向请求头添加或修改字段。我们能不能手动将修改 referer字段呢?

(1)test.js

// 通过ajax下载图片
function loadImage(uri) {
    return new Promise(resolve => { //使用异步下载 
        let xhr = new XMLHttpRequest(); //实例化xmlhttprequest
        xhr.responseType = "blob"; //响应类型为blob(二进制)
        xhr.onload = function () {
            resolve(xhr.response);
        };

        xhr.open("GET", uri, true);
        xhr.setRequestHeader("Referer", "");
        // 通过setRequestHeader设置header不会生效
        xhr.send();
    });
}

// 将下载下来的二进制大对象数据转换成base64,然后展示在页面上
function handleBlob(blob) {
    let reader = new FileReader();
    reader.onload = function (evt) { //监听事件
        let img = document.createElement('img');
        img.src = evt.target.result;
        document.getElementById('container').appendChild(img)
    };
    reader.readAsDataURL(blob);
}

const imgSrc = "https://profile-avatar.csdnimg.cn/8f0b72eabecc42df84ef2cce29ed569a_qq_68163788.jpg!1";
loadImage(imgSrc).then(blob => {
    handleBlob(blob);
});

(2)referrer1.html

<div id="container">aaa</div>
<script src="./test.js"></script>

(3)测试

 上述代码运行时会发现控制台提示错误

根据结果可以看出,浏览器拒绝将Rerrer置为空

可以看见setRequestHeader设置referer响应头是无效的,这是由于浏览器为了安全起见,无法手动设置部分保留字段,不幸的是Referer恰好就是保留字段之一,详情列表参考Forbidden header name。

可见使用xmlhttprequest提供的方法用AJAX同源请求无法完成这一操作。

使用fetch可以解决这一问题。

利用fetch

Fetch是浏览器提供的一个全新的接口,用于访问和操作HTTP管道部分,例如请求和响应,该接口支持referrerPolicy,因此也可以用来操作referer。

// 将下载下来的二进制大对象数据转换成base64,然后展示在页面上
function handleBlob(blob) {
    let reader = new FileReader();
    reader.onload = function (evt) {
        let img = document.createElement('img');
        img.src = evt.target.result;
        document.getElementById('container').appendChild(img)
    };
    reader.readAsDataURL(blob);
}

const imgSrc = "https://img-blog.csdnimg.cn/5ff039c8a8cd47c98e26d694854e8962.jpeg";


function fetchImage(url) {
    return fetch(url, {
        headers: {
            // "Referer": "", // 这里设置无效
        },
        method: "GET",
        referrer: "", // 将referer置空
        // referrerPolicy: 'no-referrer', 
    }).then(response => response.blob());
}

fetchImage(imgSrc).then(blob => {
    handleBlob(blob);
});

 

通过将配置参数redirect置位空,可以看见本次请求已经不带referer了。

防盗链是指为了阻止其他网站或用户在未经授权的情况下盗用自己网站的资源而采取的一种措施。在Python中,可以通过设置请求头中的"Referer"字段来进行防盗链。 在给定的代码中,通过设置请求头的"referer"字段来模拟请求时的来源页面。这样,被请求的服务器可以根据Referer字段来判断请求的合法性。如果请求的Referer字段与服务器期望的来源页面匹配,则服务器会正常返回请求的资源。否则,服务器可能会返回错误或者拒绝提供资源。 具体来说,在代码中的header字典中设置了"referer"字段的值为"https://www.pearvideo.com/video_1160135",这是一个示例的来源页面链接。根据实际情况,可以将该字段的值设置为合法的来源页面链接。 在请求中,会根据提供的链接获取视频资源的URL,并进行一些拼接替换操作,最终得到视频的真实URL。然后可以使用Python的requests库发送GET请求,获取到视频资源的内容,并进行保存。 总结起来,这段Python代码通过设置请求头的Referer字段来模拟合法的请求来源,从而实现防盗链的效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python爬虫学习--防盗链](https://blog.csdn.net/weixin_30675247/article/details/95668172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python--爬虫,了解防盗链-->解决防盗链,解决反反反爬](https://blog.csdn.net/qq_57663276/article/details/127474123)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未知百分百

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值