10

判断浏览器User-Agent是否伪造的常规方法

 1 year ago
source link: https://easeapi.com/blog/174-useragent-fake-detect.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

判断浏览器User-Agent是否伪造的常规方法

原创 2023-05-23

User-Agent使用一串特定的字符串来标识网络客户端信息,User-Agent常被网站用于平台判断、爬虫检测等。本文介绍一些判断User-Agent是否伪造的常规方法。

一、User-Agent的格式

User-Agent是网络客户端发起HTTP请求时的一个标准 Header 字段,它使用一串特定的字符串来标识网络客户端信息。User-Agent非常重要,它常常被网站用于平台判断、爬虫检测等。

绝大所数网页浏览器都使用如下格式的 User-Agent 值:

Mozilla/[version] ([system and browser information]) [platform] ([platform details]) [extensions]

下面是一个典型的 FireFox 浏览器的 User-Agent 值:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0
  • Mozilla/5.0

Mozilla/5.0 是一个通用前缀,表示与 Mozilla 兼容,这几乎是现代网页浏览器的标配。这里面涉及到复杂的历史渊源,这篇文章为什么所有主流浏览器的 User-Agent 都是 Mozilla/x.0 开头有详细解释。

  • Macintosh; Intel Mac OS X 10.15; rv:109.0

标识运行浏览器的操作系统信息。

  • Gecko/20100101

浏览器使用的渲染引擎信息。

  • Firefox/113.0

浏览器的具体信息(版本)。

由于复杂的历史演变原因,主流浏览器的User-Agent往往是上述格式的变体。下面是笔者实际测试不同浏览器的User-Agent值:

  • macOS Chrome
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
  • macOS Safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15
  • macOS Microsoft Edge
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50
  • iPhone Safari
Mozilla/5.0 (iPhone; CPU iPhone OS 15_7_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.4 Mobile/15E148 Safari/604.1
  • Android Chrome
Mozilla/5.0 (Linux; Android 7.1.2; Pixel) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36

国内厂商浏览器的 User-Agent 格式更是复杂,下面是 iPhone 手机百度浏览器的User-Agent值:

Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.71.0 main%2F1.0 baiduboxapp/13.33.0.12 (Baidu; P2 16.5) NABar/1.0 themeUA=Theme/default webCore=0x151f32990

这串信息如此冗长,后半段表达的内容恐怕只有百度自己才能搞明白。

二、判断客户端User-Agent是否是伪造过的

User-Agent信息非常重要但因为其是明文易读的字符串,是很容易被篡改的。对于精心设计的网络爬虫来说,可以伪造任意系统、任意浏览器版本的 User-Agent ,来模拟正常用户的访问请求。大量爬虫的请求会对系统服务造成较大压力且很容易爬取到大量敏感数据,解决这个问题除了可以在访问频次、行为异常等方面限制,还可以通过判断 User-Agent 是否被篡改来区分请求恶意请求。

常规的判断方式是搜集更多的信息,以便和User-Agent值对比,当出现不匹配的情形时视为伪造。

TCP/IP指纹

HTTP 使用 TCP/IP 作为底层传输协议。考虑到跨操作系统和操作系统版本在 TCP 实现存在差异,可通过 TCP 头部及标志等信息来判断来自特定的操作系统。如果通过 TCP指纹信息检测属于Linux系统,则该请求的 User-Agent 不可能为 Windows系统。

p0f是一款基于分析TCP/IP协议信息的探测工具,可以通过捕获并分析目标主机发送的数据包来对主机使用的操作系统进行识别。典型的嗅探结果示例如下:

.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (syn) ]-
|
| client   = 1.2.3.4
| os       = Windows XP
| dist     = 8
| params   = none
| raw_sig  = 4:120+8:0:1452:65535,0:mss,nop,nop,sok:df,id+:0
|
`----

.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (mtu) ]-
|
| client   = 1.2.3.4
| link     = DSL
| raw_mtu  = 1492
|
`----

.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (uptime) ]-
|
| client   = 1.2.3.4
| uptime   = 0 days 11 hrs 16 min (modulo 198 days)
| raw_freq = 250.00 Hz
|
|
`----

.-[ 1.2.3.4/1524 -> 4.3.2.1/80 (http request) ]-
|
| client   = 1.2.3.4/1524
| app      = Firefox 5.x or newer
| lang     = English
| params   = none
| raw_sig  = 1:Host,User-Agent,Accept=[text/html,application/xhtml+xml...
|
`----

HTTP信息

除了User-Agent,HTTP请求的Header中还有很多字段。下面是使用FireFox浏览器请求本博客首页时的完整header信息:

GET /blog HTTP/2
Host: easeapi.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: https://easeapi.com/
Connection: keep-alive
Cookie: ...
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
TE: trailers

如果用Chrome浏览器发起同样的请求,就会发现会多了几个header:

Sec-Ch-Ua: "Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"

不仅如此,其AcceptAccept-Language字段的内容也和FireFox有区别:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7

另外,两者部分请求header的顺序也不一样,在 Firefox 中,User-Agent是在最前面,而在 Chrome 中 User-Agent 则位于最后面。

JavaScript特性

window.navigator属性

window.navigator结构中除了userAgent属性,还有vendor、platform、oscpu等属性可以区分。

  • Chorme
window.navigator.vendor -> Google Inc.
window.navigator.platform -> MacIntel
window.navigator.oscpu ->
  • FireFox
window.navigator.vendor ->
window.navigator.platform -> MacIntel
window.navigator.oscpu -> Intel Mac OS X 10.15
  • Safari
window.navigator.vendor: Apple Computer, Inc.
window.navigator.platform: MacIntel
window.navigator.oscpu: undefined

CSS特性

浏览器通常有自己的非标准 CSS 特性。我们可以使用JS方法CSS.supports来检查是否支持指定的CSS特性。比如:

  • Chrome
CSS.supports("-webkit-border-vertical-spacing", 0) -> true
CSS.supports("-moz-user-focus", "normal") -> false
CSS.supports("-moz-box-sizing", "content-box") -> false
  • Firefox
CSS.supports("-webkit-border-vertical-spacing", 0) -> false
CSS.supports("-moz-user-focus", "normal") -> true
CSS.supports("-moz-box-sizing", "content-box") -> true

特殊的window属性

不同的浏览器可能会增加不同的window属性。

  • Chrome
window.webkitCancelAnimationFrame !== undefined -> true
window.mozInnerScreenX !== undefined -> false
window.chrome !== undefined -> true
  • Firefox
window.webkitCancelAnimationFrame !== undefined -> false
window.mozInnerScreenX !== undefined -> true
window.chrome !== undefined -> false

传统的检查方法的局限性

以上检查方法可以和User-Agent信息进行对比以判断是否伪造。但同时我们可以发现一个问题,这些可以用于区分的信息和 User-Agent 没有什么本质区别,都是含义明确的明文字符串,攻击者同样可以任意修改来伪造和普通用户一摸一样的请求。也就是说,即使我们能找到足够多的区分信息,攻击者可以轻松地像修改 User-Agent 一样去修改这些信息的值。

相关文章:

浏览器的 Secure Context 安全上下文限制
使用mkcert生成自签名证书


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK