current position:Home>Referer and referer policy and picture anti-theft chain

Referer and referer policy and picture anti-theft chain

2022-04-29 13:03:12Fine road

Referer

Referer The request header contains the address of the source page of the current request page , It means that the current page is entered through the link in this source page . The server generally uses Referer( notes : Correct English spelling should be referrer, Because of the early HTTP Standard spelling mistakes , In order to maintain backward compatibility, it continues ) The request header identifies the access source , May use this statistical analysis 、 Logging and cache optimization .

  notes : Referer The request header may expose the user's browsing history 、 User privacy concerns .

Referrer-policy

Referrer-policy The function is to control the... In the request header referer The content of

Include the following values :

  • no-referrer : Whole referee The first one will be removed , Access source information is not sent with the request .
  • no-referrer-when-downgrade :  The default behavior of a user agent without specifying any policy . In the same level of security , The address of the reference page will be sent (HTTPS->HTTPS), But will not be sent in case of demotion (HTTPS->HTTP).
  • origin:  In any case , Send only the source of the file as the reference address . for example   example.com/page.html  Meeting …
  • origin-when-cross-origin:  For homologous requests , Will send the complete URL As a reference address , But for non homologous requests only send the source of the file .
  • same-origin: For requests of the same origin, the reference address will be sent , However, for non homologous requests, the reference address information is not sent .
  • strict-origin:  In the same level of security , Send the source of the file as the reference address (HTTPS->HTTPS), In the case of sending... But not degraded (HTTPS->HTTP).
  • strict-origin-when-cross-origin:  For homologous requests , Will send the complete URL As a reference address ; In the same level of security , Send the source of the file as the reference address (HTTPS->HTTPS); Do not send this header in case of degradation (HTTPS->HTTP).
  • unsafe-url:  Whether it's a homologous request or a non homologous request , Send the complete URL( After removing the parameter information ) As a reference address .( The least safe )

Browser compatibility (caniuse.com/?search=ref…

How to set up referer

  1. stay HTML Set in the meta 
<meta name="referrer" content="origin">
 Copy code 

Here's the picture :

  1. Or use <a>、<area>、<img>、<iframe>、<script>  perhaps <link>  Element  referrerpolicy  Property to set a separate request policy for it .

Such as :

<script src='/javascripts/test.js' referrerpolicy="no-referrer"></script>
 Copy code 



Not added referrerpolicy Attribute link Elements :

Stealing chain

Steal chain is to show some content on your own page that is not on your own server , Get someone else's resource address , Bypass other people's resource display page , Provide this content directly to end users on your own page . Generally, those who have been stolen are picture 、 Executable file 、 Audio and video files 、 Compressed files And so on . By means of stealing chain, you can reduce the burden of your own server

For example, introduce a photo in Baidu Post Bar into your own page :

<body>
    <img src="https://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg"> 
</body>
 Copy code 

It's actually impossible to show ( Here's the picture ), The reason why it can't be displayed is that Baidu's pictures have been processed by anti-theft chain

How the chain works

adopt Referer Or sign , The website can detect the source page visited by the target page , If it's a resource file , Then you can trace to the web page address that displays it Once it is detected that the source is not the site , That is to block or return to the specified page

Bypass the picture anti-theft chain

So how do many websites use now referer To prevent image chain theft ?
In three cases, it is allowed to quote pictures :

  1. This web site .
  2. nothing referer Information .( The server thinks it's a picture accessed directly from the browser URL, So it can be accessed normally )
  3. Authorized website .

We can only learn from the situation 2 Starting with , By setting referer Empty to bypass the anti-theft chain .

utilize https Website theft http Resource Website ,refer Don't send

First use of openssl Generate a self-signed certificate ( Specific to see github.com/zxl92576866…
client.js

let https = require("https");
let fs = require("fs");
let url = require("url");
let path = require("path");


var options = {
  hostname: "localhost",
  port: 8000,
  path: "/",
  method: "GET",
  rejectUnauthorized: false,
  key: fs.readFileSync("./keys/client.key"),
  cert: fs.readFileSync("./keys/client.crt"),
  ca: [fs.readFileSync("../ca/ca.crt")],
};

//  Create a server 
https.createServer(options, function (req, res) {

  let staticPath = path.join(__dirname, "src");
  let pathObj = url.parse(req.url, true);

  if (pathObj.pathname === "/") {
    pathObj.pathname += "index.html";
  }
  //  Read the files in the static Directory , And send it out 
  let filePath = path.join(staticPath, pathObj.pathname);
  fs.readFile(filePath, "binary", function (err, content) {
    if (err) {
      res.writeHead(404, "Not Found");
      res.end("<h1>404 Not Found</h1>");
    } else {
      res.writeHead(200, "Not Found");
      res.write(content, "binary");
      res.end();
    }
  });

}).listen(8080);

 Copy code 

index.html

<div id="container">
    <img src="http://localhost:9999">
</div>
 Copy code 

The startup results are as follows :
Tips : Because we use a self signed certificate , When you visit the page, you may see the certificate warning of the browser , You may need to manually click trust current certificate , Or manually click the link to confirm access to the page . for example Chrome remind “ Your connection is not private ”, And prohibit you from visiting . You can enter... Directly on the current page thisisunsafe, Not in the address bar , Instead, just tap the keyboard to enter , The page will automatically refresh and enter the web page .

Set up meta

<meta name="referrer" content="no-referrer" />
 Copy code 

Set up referrerpolicy="no-referrer"

The above has been verified , There are only some compatibility problems .

images.weserv.nl/?url=`${ Your picture …

Because the website is foreign, the speed is a little slow, and the effect is OK , The purpose is to return an unrestricted picture , however GIF The format will return jpg That is, there is no animation effect .

utilize iframe Falsify a request referer

Content reference juejin.cn/post/684490…

function showImg(src, wrapper ) {
    let url = new URL(src);
    let frameid = 'frameimg' + Math.random();
    window.img = `<img id="tmpImg" width=400 src="${url}" alt=" Image load failed , Please try again later "/> `;

    //  Construct a iframe
    iframe = document.createElement('iframe')
    iframe.id = frameid
    iframe.src = "javascript:parent.img;" //  Through inline javascript, Set up iframe Of src
    //  correction iframe The size of the , Show the picture in full 
    iframe.onload = function () {
        var img = iframe.contentDocument.getElementById("tmpImg")
        if (img) {
            iframe.height = img.height + 'px'
            iframe.width = img.width + 'px'
        }
    }
    iframe.width = 10
    iframe.height = 10
    iframe.scrolling = "no"
    iframe.frameBorder = "0"
    wrapper.appendChild(iframe)
}

showImg('https://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg', document.querySelector('#container'))
 Copy code 

give the result as follows :

The client modifies when requested header Head

Content reference juejin.cn/post/684490…

utilize XMLHttpRequest

XMLHttpRequest in setRequestHeader Method , Used to add or modify fields... To the request header . Can we manually change referer Field ?

//  adopt ajax Download the pictures 
function loadImage(uri) {
    return new Promise(resolve => {
        let xhr = new XMLHttpRequest();
        xhr.responseType = "blob";
        xhr.onload = function() {
            resolve(xhr.response);
        };

        xhr.open("GET", uri, true);
        //  adopt setRequestHeader Set up header Will not enter into force 
        //  Will prompt  Refused to set unsafe header "Referer"
        xhr.setRequestHeader("Referer", ""); 
        xhr.send();
    });
}
  

//  Convert the downloaded binary big object data into base64, Then show it on the page 
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://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg";

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

 Copy code 

When the above code runs, you will find the console prompt error :

Refused to set unsafe header "Referer"

Can see setRequestHeader Set up referer The response header is invalid , This is because the browser is for security , Can't set some reserved fields manually , Unfortunately Referer It happens to be one of the reserved fields , Refer to Forbidden header name.

utilize fetch

//  Convert the downloaded binary big object data into base64, Then show it on the page 
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://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg";


function fetchImage(url) {
    return fetch(url, {
        headers: {
            // "Referer": "", //  The setting here is invalid 
        },
        method: "GET",  
        referrer: "", //  take referer empty 
        // referrerPolicy: 'no-referrer', 
    }).then(response => response.blob());
}

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

By setting the configuration parameters referrer empty , It can be seen that this request has not taken referer 了

Or set up referrerPolicy by "no-referrer"

The server makes anti-theft chain picture transfer

Here we use express
index.js

const express = require('express');
const app = express();

app.use('/img', require('./routers/index.js'))

app.listen(3000);
 Copy code 

routers/index.js

var express = require('express');
var router = express.Router();
var request = require('request');

router.get('/', function(req, res, next) {
    var options = {
        method: 'GET',
        url: 'https://tiebapic.baidu.com/forum/w%3D580%3B/sign=f88eb0f2cf82b9013dadc33b43b6ab77/562c11dfa9ec8a135455cc35b203918fa1ecc09c.jpg',
        headers: {
            'Referer': '',
        }
    };
    request(options).pipe(res)
    
});

module.exports = router;
 Copy code 

Common anti-theft chain methods

The anti-theft chain generally has the following ways :

  1. Dynamic filename , Or modify the file name or path regularly
  2. Determine the reference address , Generally, when judging the browser request HTTP The head of the Referer Value of field
  3. Use login authentication ,cookie
  4. Watermark the picture
  5. ...

utilize nginx

ngx_http_referer_module Used to block requests from illegal domain names nginx Instructions valid_refers, Global variables $invalid_refer Security chain of resources nginx Configure to

location ~.*\.(gif|jpg|png|bmp|flv|swf|rar|zip)$
{
    valid_referers none blocked test.com *.test.com;   //  Add none The goal is to ensure that browsers can access resources directly 
    if($invalid_referer)
    {
        #return 403;  //  Go straight back to 403
        rewrite ^/ http://www.test.com/403.jpg; //  Returns the specified prompt image 
    }
}
 Copy code 

This method is in server perhaps location Add :valid_referers. The order is in referer The head is based on $invalid_referer Variable assignment , Its value is 0 or 1. If valid_referers Not in the list Referer Head value , $invalid_referer Will be set to 1.
If $invalid_referer be equal to 1, stay if Statement returns a 403 To the user , So the user will see a 403 The page of , If you use the following rewrite, Then the images of the stolen chain will be displayed 403.jpg.
The instruction supports none and blocked:

  • among none Means the way of emptiness , That is, direct access , For example, open a file directly in the browser
  • blocked Indicates the way marked by the firewall ,*..com Indicates all subdomains

But the traditional anti-theft chain will also have some problems , because refer It can be forged , So we can use encrypted signature to solve this problem . What is an encrypted signature ? It's when we ask for an image , I'll bring it some signatures , Then when we return to the image, we judge whether the signature is correct , It's equivalent to a code .
Please refer to zhuanlan.zhihu.com/p/362650878

Server side judgment referer

We can compare req.headers['referer'] and req.url Medium host To confirm whether the resource request is from another site . next , When we know the source of the resource request , We can decide whether to respond to the request and how to respond through a series of means . The usual practice is to set up a white list , We respond to requests on the white list , Otherwise, it will not respond .

let http = require("http");
let fs = require("fs");
let url = require("url");
let path = require("path");
//  White list 
const whiteList = ["localhost:8080"];

/** *  In three cases, it is allowed to quote pictures : * 1.  This web site  * 2.  nothing referer Information .( The server thinks it's a picture accessed directly from the browser URL, So it can be accessed normally ) * 3.  Authorized website .( Configure white list ) */

http
  .createServer(function (req, res) {

    let refer = req.headers["referer"] || req.headers["refer"];
    console.log('refer----', refer, req.url);
    res.setHeader("Access-Control-Allow-Origin", "*");
    if (refer) {
      let referHostName = url.parse(refer, true).host;
      let currentHostName = url.parse(req.url, true).host;
      console.log(referHostName, currentHostName, '--==')
      //  When referer Not empty ,  but host When the target website is not hit and is not on the whitelist ,  Return the wrong graph 
      if (
        referHostName != currentHostName &&
        whiteList.indexOf(referHostName) == -1
      ) {
        res.setHeader("Content-Type", "image/jpeg");
        fs.createReadStream(path.join(__dirname, "/src/img/403.jpg")).pipe(res);
        return;
      }
    }
    //  When referer It's empty time ,  Return to the correct diagram 
    res.setHeader("Content-Type", "image/jpeg");
    fs.createReadStream(path.join(__dirname, "/src/img/1.jpg")).pipe(res);
    
  })
  .listen(9999);

 Copy code 

utilize http Start a client :
client.js

let http = require("http");
let fs = require("fs");
let url = require("url");
let path = require("path");

//  Create a server 
http.createServer(function (req, res) {
  let staticPath = path.join(__dirname, "src");
  let pathObj = url.parse(req.url, true);

  if (pathObj.pathname === "/") {
    pathObj.pathname += "index.html";
  }
  //  Read the files in the static Directory , And send it out 
  let filePath = path.join(staticPath, pathObj.pathname);
  fs.readFile(filePath, "binary", function (err, content) {
    if (err) {
      res.writeHead(404, "Not Found");
      res.end("<h1>404 Not Found</h1>");
    } else {
      res.writeHead(200, "Not Found");
      res.write(content, "binary");
      res.end();
    }
  });
}).listen(8080);

 Copy code 

index.html

<div id="container">
    <img src="http://localhost:9999"> </div>
 Copy code 

Start the client and server respectively :

If we modify the server side whiteList:

//  White list 
const whiteList = [];
 Copy code 

Restart the server , After accessing the client We found that the response turned out to be 403 picture :

403.png

Prevent the website from being iframe

Add the following code at the bottom of the page or other common parts :

//  use js Method to check whether the domain name in the address bar is the domain name bound to the current website , If not , Then jump to the bound domain name , In this way, you are not afraid of the website being used by others iframe 了 
if(window!=parent) {
    window.top.location.href = window.location.href; 
}
 Copy code 

notes :
The above code address has been submitted GitHub: github.com/zxl92576866…

Reference material :

developer.mozilla.org/zh-CN/docs/…

developer.mozilla.org/zh-CN/docs/…

juejin.cn/post/684490…

juejin.cn/post/684490…

www.cnblogs.com/wangyongson…

copyright notice
author[Fine road],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/04/202204291303063810.html

Random recommended