一个网段里 10 个 IP,其实是同一个人:13 天蜜罐日志的攻击者画像

变量探索(SEQVEC)

上一篇写的是"我埋了什么、他们怎么上钩"。这一篇换个角度:日志里那一堆 IP,到底谁是谁。

先更新数据 ------ 蜜罐跑到第 13 天:

复制代码
原始记录      583 条
剔除自己      475 条
独立真实 IP   157 个
涉及站点      13 个

比上一篇的 502 次又往上走了一截。而且有意思的是:它没有衰减。

下面是这些天整理日志时总结出的一套识别方法。不需要任何安全产品,一台服务器加一个日志文件就够。

数据说明 :下面所有数字都是剔除自己之后的 475 条。 属于我自己的 108 条单独统计,见第一步。


第 0 步:先确认你看到的 IP 是不是真的

这一步是我这次差点栽进去的地方,所以放在最前面。

我一开始按日志里的 IP 做统计,出现了一个说不通的现象:

复制代码
43.175.168.191   34 次   打过 8 个不同子域名   出现过 9 种不同 UA
43.175.168.101   29 次   打过 5 个不同子域名   出现过 14 种不同 UA

一个攻击者只有一种工具。 一个 IP 上同时出现 curl、企业扫描器、泄露情报采集、 还有伪装成 Chrome 的脚本 ------ 那是好几家公司在扫。而且它还在打你不同的域名。

这只可能是一种东西:共享中间节点。

顺着查下去,43.174 / 43.175 这两个段里的 24 个 IP,占了 500 条样本里的 204 条 ------ 40.8%。它们属于同一个 AS、同一批机房。

再往下就想明白了:这个站前面挂了 CDN。 源站 nginx 的 $remote_addr 记的是 CDN 的回源节点 IP,不是访客 IP。

而真实客户端 IP 一直在同一个日志文件里 ------ 在 X-Forwarded-For 里:

json 复制代码
{"ip":"43.175.168.101",  "xff":"160.176.79.216", ...}
   ↑ CDN 回源节点              ↑ 真实访客,一直都在

我早先的日志格式里其实记了 xff 字段,只是分析脚本读的是 ip。 数据没丢,是我读错了字段。

修法是源站这边两行:

nginx 复制代码
set_real_ip_from <CDN 回源段>;
real_ip_header X-Forwarded-For;

配好之后 $remote_addr 直接变成真实 IP,日志、脚本、报表全部自动就对了, 下游一行都不用改。

留一条判断手法

以后再遇到"日志里全是同一个机房"的情况,用这一条就够了:

看一个 IP 打了几种 UA、几个 host。

复制代码
真实来源    1 种 UA,1--2 个站
中间节点    多种 UA,多个站

这也顺带说明一件事:在 IP 上做任何结论之前,先确认这个 IP 是不是真的。 这一篇的数字,全部是按真实客户端 IP 重算的。


第一步:先把自己清出去

583 条里,有 108 条是我自己:

lua 复制代码
127.0.0.1          45 次   ← 本机验证(curl、hx-direct、hx-verify-local)
49.233.178.207     34 次   ← 服务器通过公网访问自己的站点(监控)
123.156.181.145    29 次   ← 我自己的出口 IP(浏览和手动测试)

127.0.0.1 以 45 次排在全表第一 ------ 如果不清掉,它就是"最活跃的攻击者"。

不清掉会污染好几个统计:

  • 独立 IP 数虚高
  • "最活跃 IP"榜单被自己占位置
  • 按 UA 分类时会多出一组根本不存在的"攻击者"

而且这次因为 CDN 的事,清自己这件事要做两遍:

复制代码
第一遍   按原始 IP 清(127.0.0.1、服务器自己的公网地址)
第二遍   换成真实 IP 之后,把你自己的出口 IP 再加进去

第二遍漏了的话,我的出口 IP 会稳稳排在真实 IP 榜的第一名。

所以第一件事永远是:用你自己的 UA 特征、你自己的出口 IP、你自己的验证时间点, 把自家的记录摘出去。 这步不花时间,但不做的话后面全是脏数据。


第二步:看 User-Agent,有三种一眼就是假的

UA 是最容易伪装的字段,但伪装本身会留下痕迹。这些天我见到三类破绽。

第一类:裸奔的 UA(119 次)

ini 复制代码
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36

看着像 Chrome 对吧?它不是。

真实的 Chrome UA 结尾一定有 Chrome/版本号 Safari/537.36 这一段。 上面这串只有 WebKit 声明,没有浏览器版本 ------ 这是脚本作者随手从网上抄了一半 UA 的结果。

这一类的路径极其一致:只有 /.env 和 /config.json 两个,来回扫。

第二类:全零的补丁号(146 次)

复制代码
Chrome/147.0.0.0
Chrome/148.0.0.0

版本号可以随便写,但真浏览器的版本号长什么样是有规律的:

markdown 复制代码
Chrome/131.0.6778.86 Safari/537.36
       └┬─┘ └──┬───┘ └┬┘
        主版本   构建号  补丁号

构建号和补丁号是一串具体数字。而上面那两串是 147.0.0.0、148.0.0.0 ------ 后三段全是零。

真实浏览器的补丁号不会长期是 0。全零意味着这是个占位符: 写脚本的人图省事,只改了主版本号就发出去了。

这一类有 146 次,是所有"假身份"里最多的一种 ------ 占了有效记录的三成。

第三类:自报家门的(这一类反而不必防)

sql 复制代码
Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/...
Mozilla/5.0 (l9scan/2.0....; +https://leakix.net)
Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; Shap-User/0.1.0
Mozilla/5.0 (compatible; CertLabBot/1.0; certificate research; single GET of the home page)

四家专业扫描服务,UA 里写着公司名和用途说明,有的还附文档地址:

复制代码
泄露情报采集(LeakIX)     49 次   来自 23 个不同 IP
攻击面扫描(Palo Alto)    11 次   来自 11 个不同 IP
空间测绘(Shap)            6 次   来自  4 个不同 IP
证书研究(CertLabBot)      6 次   来自  1 个 IP

它们不伪装,因为没必要。 商业攻击面扫描、泄露情报采集、网络空间测绘, 这些业务本身就是公开的 ------ 被发现是工作的一部分,藏起来反而违规。

所以判断规则可以简化成一句:

承认自己在扫描的,通常是行业惯例;假装自己是浏览器的,才值得留意。


第三步:看路径,请求什么就暴露了什么意图

有效记录里,访问量排前几位的路径:

bash 复制代码
281 次   /.env
154 次   /config.json
 19 次   /.well-known/security.txt
  7 次   /backup/
  7 次   /backup/.env
  3 次   /_notice

/.env 和 /config.json 两个加起来,占了全部访问的 92%。

这个规律和上一篇一致 ------ 因为它们跨框架通用,一个脚本能扫遍全网,投入产出比最高。

但路径的价值不在排名,在于区分人:

行为模式 特征 典型例子
广撒网 只碰 /.env 和 /config.json,高频、机械、路径不变 那两类假 UA 背后的 IP
按规程 只请求 /.well-known/security.txt,其他一概不碰 商业攻击面扫描,11 次全部只碰这一个文件
有目的 直奔 /backup/ 下的具体文件名 4 次访问直奔那个假数据库导出

第三种最值得注意。浏览可能是爬虫顺手,直奔具体文件名说明他已经知道他在找什么。

还有个细节:这次记录里出现了几次路径变形的尝试:

bash 复制代码
/.//.env
//.env
/%2eenv
/api/uploads/%2e%2e%2f%2e%2e%2f.env      ← 路径穿越

这些都是在试着绕开服务器的路径匹配规则。会做这一步的,说明前面已经扫到了响应, 正在琢磨怎么拿到更多。

顺便说一句:/.well-known/security.txt 本来是"安全研究者联系我"的标准声明文件, 商业扫描器会先读它 ------ 这不是攻击行为,是行业里打招呼的方式。 如果你打算做安全这件事,这个文件建议放上,它是免费的。


第四步:看网段 ------ IP 不是身份,行为才是

这是整篇文章我最想讲的一点。

按 IP 单独统计,"最活跃"前几名看着像十几个不同的人。但把网段 + 行为放一起看, 有一个人立刻显形:

markdown 复制代码
45.138.12.16    2 次
45.138.12.22    6 次
45.138.12.23    6 次
45.138.12.24    2 次
45.138.12.25    3 次
45.138.12.28    8 次
45.138.12.30    6 次
45.138.12.52    1 次
45.138.12.53   15 次
45.138.12.54    6 次
               ──────
               10 个 IP,合计 55 次

一个 /24 段里 10 个 IP,UA 是同一串裸奔 UA,只碰同样的路径,轮流出现。

查了一下归属:AS218785 TC DATACENTER LIMITED,波兰。

看起来是十个攻击者,实际上是一个人 ------ 他手上有一小段 IP,轮着用。 而且几乎可以确定租的是同一家的机器。

把范围放大,"同一个人"的证据更清楚:那串裸奔 UA 一共出现 119 次, 来自 24 个不同的真实 IP。

反过来也成立 ------ 同一个 IP 也可能属于不同的人(云主机上的多租户、代理池、跳板)。 所以:

按 IP 统计只能得到"有多少个地址", 按行为聚类才能得到"有多少个人"。

具体怎么聚类?我用的是最土的办法:UA + 路径集合 + 时间节奏,三个都对上就归为一簇。 不需要算法,一张表格就能看出来。

顺带算出一个更有意思的:这批人都是在哪儿干活的

把点击量靠前的真实 IP 抽出来查归属:

复制代码
34.140.132.132   Google LLC(AS396982)
35.205.254.119   Google LLC(AS396982)
94.154.43.125    Storm Industries LLC(荷兰)
46.151.182.7     Blatant Technologies, LLC(德国)
31.59.160.3      Miteflux Technologies Ltd(瑞典)
45.138.12.53     TC DATACENTER LIMITED(波兰)

没有一个来自家宽,全是租来的云主机。

其中最大的一股是 Google Cloud:

erlang 复制代码
34.x 段     84 次 / 22 个 IP
35.x 段     32 次 / 11 个 IP
────────────────────────────
合计       116 次 / 33 个 IP     占了有效记录的 24%,独立 IP 的两成

而且它们在行为上非常整齐:

复制代码
一个 IP 只用一个 UA,却横扫 4--7 个不同子域名

比如 34.140.132.132 ------ 打了 7 个站,总共只花了 11 次请求。

这不是撞大运的乱扫,是子域名枚举:先拿一个域名,把所有子域列出来挨个打。 效率极高,成本极低。

这件事的防守含义很直接:你的子域名就是你的暴露面。 主站做得再好,如果 admin.、test.、demo. 这些还在,扫描器会挨个试。


第五步:看时间,这次看不出作息

把 13 天的访问按小时铺开:

bash 复制代码
00 时  36 次   ####################################
01 时  36 次   ####################################
22 时  33 次   #################################
12 时  33 次   #################################
17 时  29 次   #############################
10 时  27 次   ###########################
02 时  26 次   ##########################
...
08 时   7 次   #######
16 时   6 次   ######

深夜(22--01 时)确实略高,四个小时合计 119 次,占了 25%。 但白天也有明显高峰:12 时 33 次、17 时 29 次。

整体相当平。

这个结论和"深夜异常"的直觉不一样,但我更愿意如实写下来: 这个分布就是自动化在跑的样子,看不出有人在挑时间。

这是这一篇里我唯一没得出确定结论的一步。写下来是因为它本身有价值: 如果你看到的是"某个时段突然扎堆",那才说明背后有人在盯着; 像这样铺开的,基本就是机器。


第六步:那这些画像,防守时怎么用

先说清楚一件事:不要反制。

主动反打回去在技术上不可靠(对方多半是跳板),在法律上有明确风险 ------ 那是网络攻击行为,不是防守。

画像真正的用途是这三个:

一、判断自己有没有被"盯上"。

随手扫和盯着打,在日志里长得不一样。随手扫是散的、路径固定的、单次请求; 盯着打会反复来、会试变形路径、会去翻备份目录。我这份数据里,四家专业扫描服务属于前者, 那几个同段 IP 轮着来的、以及直奔备份文件的,属于后者。

二、验证防护有没有生效。

那些诱饵的路径,在真实系统里本来就该返回 404。 如果你哪天在真实日志里看到它们拿到 200,说明有东西不该在那儿。

三、做溯源准备的底子。

如果你在响应里带了唯一标识(上一篇讲过这个做法),那么将来某份内部资料外流时, 你能反查到是哪一次访问带走的。前提是 ------ 你得先认得出"谁来过"。


最后

这一篇比上一篇多了一个教训,我觉得比方法本身更重要:

你以为在做画像,其实可能是在给 CDN 的节点池画像。

我一开始统计出的"最活跃攻击者"是 127.0.0.1(我自己), "第二大来源"是 CDN 的回源节点,"一个人握着一小段 IP"看起来成立, 但举的是一堆机器。

全部退回重算之后,真实的那张画像反而更清楚 ------ 一个波兰机房里的 10 个 IP 是同一个人,四分之一流量从 Google Cloud 来,扫的是子域名。

所以顺序应该是:

复制代码
先确认 IP 是真的   →   再清掉自己   →   最后才谈行为

区别不在工具,在"你决定记什么",也在"你确认过读到的是什么"。


变量探索(SEQVEC)

相关推荐
OsDepK2 小时前
OSMDE_v1.9.0已加入FTP与shell功能
linux·运维·服务器
剑锋所指,所向披靡!2 小时前
HTTP服务器的基本相关概念
服务器·网络协议·http
硅基手札2 小时前
【Linux内核专栏 11】驱动框架:platform / char / misc / 设备树
linux·运维·服务器
2301_777998343 小时前
TCP协议:滑动窗口与流量控制
服务器·网络·网络协议·tcp/ip·php
well06124 小时前
Linux 文件相关底层知识
linux·运维·服务器
库拉镜像AI牛牛5 小时前
漫剧工作室量产方案:依托知漫剧 AI 短剧降本增效
大数据·服务器·前端·人工智能·语音识别
沫璃染墨5 小时前
《从零入门Linux系统篇(五十八):线程篇·十一——线程安全与死锁详解:从可重入到多锁管理》
linux·服务器·开发语言·c++·驱动开发·安全·架构
姜鱼问生6 小时前
宝塔面板优雅下线:先 stop 再 disable 再 rm
运维·服务器
闭包不眠6 小时前
PDF文字提取交付前该检查什么
运维·服务器·图像处理·人工智能·计算机视觉·pdf