Are you headless页面无头浏览器检测绕过

本文分析了如何通过模仿真实浏览器的特征,如请求头和请求体,来绕过前端检测无头浏览器的方法。通过修改特定头部信息,如Accept-Language,可以成功欺骗检测机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 背景

研究人员开发者使用了一种检测方法,并提供了检测页面对chrome浏览器进行检测,
判断是否是无头浏览器。具体返回结果如下图。

在这里插入图片描述

在这里插入图片描述

2 检测手段分析

常见的前端检测手段即通过前端JS脚本收集数据上报,然后检测浏览器特征判断是否是无头浏览器。分析过程即看请求中使用的分析脚本及上报数据。首先打开正常浏览器可以看到如下7个请求。

在这里插入图片描述

https://arh.antoinevastel.com/bots/scannerareuhead 发出的post请求会上报设备信息,如下为截取部分结果。

{
    "plugins":[
        "Chrome PDF Plugin::Portable Document Format::internal-pdf-viewer::__application/x-google-chrome-pdf~pdf~Portable Document Format",
        "Chrome PDF Viewer::::mhjfbmdgcfjbbpaeojofohoefgiehjai::__application/pdf~pdf~",
        "Native Client::::internal-nacl-plugin::__application/x-nacl~~Native Client Executable,application/x-pnacl~~Portable Native Client Executable"
    ],
    "mimeTypes":[
        "~~application/pdf~~pdf",
        "Portable Document Format~~application/x-google-chrome-pdf~~pdf",
        "Native Client Executable~~application/x-nacl~~",
        "Portable Native Client Executable~~application/x-pnacl~~"
    ],
    "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3902.4 Safari/537.36",
    "byteLength":1,
    "gamut":[
        true,
        true,
        false,
        true
    ],
    "anyPointer":"fine",
    "anyHover":"hover",
    "appVersion":"5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3902.4 Safari/537.36",
    "appName":"Netscape",
    "appCodeName":"Mozilla",
    "onLine":true,
    "cookieEnabled":true,
    "doNotTrack":false
 }

为了绕过检测,就是让各种数据和真实设备一致。即发出的请求尽量完全一致(请求头、请求体)。首先验证设备参数的影响,从真实浏览器中提取设备数据存放在mockFinger文件中,当发送请求时将body替换观察结果。

const fingerprint = JSON.parse(
        fs.readFileSync("./mockFinger").toString()
    );

    const headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3902.4 Safari/537.36'
    };

    const page = await browser.newPage();

    await page.setRequestInterception(true);
    page.on('request', async interceptedRequest => {

        const overrides = {
            headers: {
                ...interceptedRequest.headers(),
                ...headers
            }
        };

        if (interceptedRequest.url() === 'https://arh.antoinevastel.com/bots/scannerareuhead') {
            fingerprint.uuid = await page.evaluate(() => uuid);
            fingerprint.url = page.url();
            const postData = JSON.stringify(fingerprint);
            overrides.headers['content-length'] = postData.length;
            overrides.postData = postData;
        }
        interceptedRequest.continue(overrides);

    });

    await page.goto(url);

发送请求后发现结果没变化,页面返回结果提示当前仍然是无头浏览器。 由于请求除了body外,还有header等数据。因此尝试修改header中的参数来观察结果。

修改依然通过将真实设备数据复制过来观察结果。直接修改header,在header中增加Accept-Language。再次运行页面检测提示当前浏览器不是无头浏览器。尝试将Accept-Language改为小写accept-language,发现服务端是对chrome浏览器的Accept-Language进行了存在性大小写验证。调整后即可绕过检测。

const puppeteer = require('puppeteer');

(async () => {
    const puppeteer = require('puppeteer');
    const browserOpts = {
        headless: true,
        args: ['--no-sandbox',
               '--disable-setuid-sandbox',
               '--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3902.4 Safari/537.36\',// \'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0',
               '--remote-debugging-port=9222'],
        executablePath: "/XXX/XXX/XXX/XXX/chrome-mac/Chromium.app/Contents/MacOS/Chromium"
    };
    
    const browser = await puppeteer.launch(browserOpts);
    const page = await browser.newPage();

    await page.setRequestInterception(true);
    page.on('request',(interceptRequest) => {
        const headers = Object.assign({},
            interceptRequest.headers(),{
            'Accept-Language': 'zh-CN,zh;q=0.5'
        });
        
       interceptRequest.continue({headers});
    });
    
		await page.goto('https://arh.antoinevastel.com/bots/areyouheadless');
    await browser.close();
})();

除了通过拦截的方式修改header,也可以在args参数中指定命令行参数设置语言选项 ‘–lang=zh-CN,zh;q=0.5’。而通过setExtraHTTPHeaders方法会将大写变成小写,导致无法通过检测。

3 总结

检测分析通常使用脚本收集浏览器特征来分析。但访问一个网站还会发出很多请求,因此除了脚本上报特征也需要关注请求数据。模拟设备与真实设备依然存在微小的差异点。因此在反爬工作与爬虫工作中应从访问的流程上全面考虑可获取到的信息,并通过分析系统分析。

4 参考

[1]对象的简洁表示,http://es6.ruanyifeng.com/#docs/object
[2]chrome命令行参数,https://peter.sh/experiments/chromium-command-line-switches/
[3]are you headless分析,https://news.ycombinator.com/item?id=20479015
[4]request.continue方法,https://github.com/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md#requestcontinueoverrides

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值