哪些请求标头可用于浏览器/客户端指纹?
Posted
技术标签:
【中文标题】哪些请求标头可用于浏览器/客户端指纹?【英文标题】:Which request headers can be used for a browser/client fingerprint? 【发布时间】:2013-07-23 14:49:42 【问题描述】:为了增加安全性,我们的服务器会跟踪浏览器指纹。目前我们使用以下标题:
'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'(取第一个非空的作为client-IP) HTTP_ACCEPTxxxx HTTP_USER_AGENT还有更多(可选的)标题可以使用吗?
一般来说,计算客户端指纹的最佳“算法”是什么?
【问题讨论】:
仅供参考,所有这些信息都可以被欺骗,但是可以使用USER_AGENT和IP地址... 你让任何人都可以在这里欺骗别人的指纹,恭喜。只有REMOTE_ADDR
保证是正确的,其他的都是任意用户提供的信息。您永远不应该使用任何替代 *_IP 标头,除非您确切知道您控制下的代理已设置它们。简而言之,这几乎是任何类型的 HTTP 标头指纹识别的问题。
@deceze:对于IP,并不是所有用户都有公共IP,很多用户可能使用一个公共IP(在我的国家至少有10,000个用户在一个IP后面)
Deceze:注意“安全”之前的“添加”一词。
@Patrick 当然,我没想到这是您唯一的安全措施。由于上述问题,它仍然存在问题,以至于添加它几乎没有意义。此外,IP 可以随时出于完全正当的理由而更改,因此要求它们保持不变可能会让用户非常恼火。
【参考方案1】:
您可以使用唯一的浏览器指纹(用户代理、Web 浏览器、画布等)并在获取哈希后。
/* Generate a fingerprint string for the browser */
function generateFingerprint()
//Generate a string based on "stable" information taken from the browser
//We call here "stable information", information that normally don't change during the user
//browse the application just after authentication
var fingerprint = [];
//Take plugins
for(var i = 0; i < navigator.plugins.length; i++)
fingerprint.push(navigator.plugins[i].name);
fingerprint.push(navigator.plugins[i].filename);
fingerprint.push(navigator.plugins[i].description);
fingerprint.push(navigator.plugins[i].version);
//Take User Agent
fingerprint.push(navigator.userAgent);
//Take Screen resolution
fingerprint.push(screen.availHeight);
fingerprint.push(screen.availWidth);
fingerprint.push(screen.colorDepth);
fingerprint.push(screen.height);
fingerprint.push(screen.pixelDepth);
fingerprint.push(screen.width);
//Take Graphical card info
//See http://output.jsbin.com/ovekor/3/
try
//Add a Canvas element if the body do not contains one
if ( $("#glcanvas").length == 0 )
$(document.body).append("<canvas id='glcanvas'></canvas>");
//Get ref on Canvas
var canvas = document.getElementById("glcanvas");
//Retrieve Canvas properties
gl = canvas.getContext("experimental-webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
fingerprint.push(gl.getParameter(gl.VERSION));
fingerprint.push(gl.getParameter(gl.SHADING_LANGUAGE_VERSION));
fingerprint.push(gl.getParameter(gl.VENDOR));
fingerprint.push(gl.getParameter(gl.RENDERER));
fingerprint.push(gl.getSupportedExtensions().join());
catch (e)
//Get also error because it's will be stable too..
fingerprint.push(e);
//Last and, in order to made this browser unique, generate a random ID that we will store
//in local storage (in order to be persistent after browser close/reopen)
//Add this ID because, in Enterprise, most of the time browser have the same configuration
var browserUniqueID = localStorage.getItem("browserUniqueID");
if (browserUniqueID === null)
localStorage.setItem("browserUniqueID", CryptoJS.lib.WordArray.random(80));
browserUniqueID = localStorage.getItem("browserUniqueID");
fingerprint.push(browserUniqueID);
return fingerprint.join();
最后得到哈希并发送到服务器。
//Call the fingerprint dedicated function
var fingerprint = generateFingerprint();
//Use CryptoJS library ot generate a hex encoded string of the hash of the fingerprint
var fingerprintHash = CryptoJS.SHA256(fingerprint);
来源:https://www.owasp.org/index.php/JSON_Web_Token_(JWT)_Cheat_Sheet_for_Java#Token_sidejacking https://browserleaks.com/canvas
【讨论】:
以上是关于哪些请求标头可用于浏览器/客户端指纹?的主要内容,如果未能解决你的问题,请参考以下文章
即使在发送 CORS 标头后从浏览器发送请求到播放服务器时也出现 CORS 错误
如何在将请求传递给上游服务器之前删除 Nginx 中的客户端标头?