网站日志怎么看有没有被入侵?我从一堆乱码里发现攻击痕迹的真实记录

去年有段时间,我的网站每隔几天就会莫名其妙地变慢。不是那种一直慢,是突然卡一下,然后恢复正常。有时候凌晨三点,有时候下午两点,没什么规律。

查了CPU、查了内存、查了数据库,都没问题。Wordfence安全插件也没报警。我一度以为是服务器商那边的问题,差点发工单去骂客服。

后来一个做运维的朋友跟我说了一句话:”你先去看日志。”

我说日志在哪?他说你不知道?

那天晚上我花了四个小时,才搞明白怎么看日志。而就在那堆看起来像乱码的东西里,我找到了一个IP地址,每隔6小时就会对我的wp-login.php发送大量POST请求——有人在暴力破解我的后台密码,已经持续了快两周了。

这篇文章就是从那晚的经历开始的。我想把”怎么看网站日志”这件事,用最不绕弯子的方式讲清楚。


网站日志是什么?先知道它在哪

网站日志就是服务器自动记录的一本”流水账”。每次有人访问你的网站、每次蜘蛛来抓取、每次有人提交表单——服务器都会记一笔。这笔记录包含:谁(IP)、什么时候(时间)、做了什么(请求类型)、访问了哪个页面(URL)、结果怎么样(状态码)。

日志文件一般在这几个位置:

服务器环境日志路径
Nginx(宝塔面板)/www/wwwlogs/你的域名.log
Apache/var/log/apache2/access.log
宝塔面板(直接看)宝塔后台 → 网站 → 设置 → 日志

如果你用的是宝塔面板,最简单——直接进后台就能看。如果不是,需要SSH连上服务器,用命令看。

我第一次连SSH的时候,打开日志文件,看到的是这样的东西:

178.128.xxx.xxx - - [15/Mar/2025:03:12:45 +0800] "POST /wp-login.php HTTP/1.1" 200 5234 "-" "Mozilla/5.0"
178.128.xxx.xxx - - [15/Mar/2025:03:12:46 +0800] "POST /wp-login.php HTTP/1.1" 200 5234 "-" "Mozilla/5.0"
178.128.xxx.xxx - - [15/Mar/2025:03:12:47 +0800] "POST /wp-login.php HTTP/1.1" 200 5234 "-" "Mozilla/5.0"

当时我完全看不懂。但等我搞明白每部分是什么意思之后,才发现这三行日志已经在尖叫了——有人在一秒内对登录页面发了三次POST请求,这根本不是正常用户的行为。


一条日志拆开看,每个部分都可能是线索

拿上面那条日志举例,把它拆开:

178.128.xxx.xxx - - [15/Mar/2025:03:12:45 +0800] "POST /wp-login.php HTTP/1.1" 200 5234 "-" "Mozilla/5.0"
字段含义这条日志里是什么
第一段访问者IP178.128.xxx.xxx(一个境外IP)
时间访问时间凌晨3点12分(正常人谁凌晨三点登录后台?)
POST/GET请求类型POST(在提交数据,不是单纯浏览)
路径访问了哪个页面/wp-login.php(登录页面)
状态码请求结果200(成功了)
UA浏览器标识Mozilla/5.0(伪装成普通浏览器)

单看一条,没什么。但如果你看到同一个IP,在凌晨三点,连续对wp-login.php发POST请求,状态码还是200——这基本可以确定是暴力破解。

我当时翻日志翻到这一段的时候,手都在抖。这个IP已经连续两周,每天凌晨三点准时来,每次发几百个请求,尝试不同的用户名密码组合。而我完全不知道。


日志里最常见的几种攻击痕迹

我把后来翻日志时遇到的几种攻击模式,整理成了一张表。如果你在日志里看到这些特征,大概率是出事了。

攻击类型日志特征怎么判断
暴力破解同一IP短时间内大量POST到wp-login.phpxmlrpc.php看频率——正常用户不会一秒钟发三次登录请求
SQL注入URL里带union select' OR '1'='1等字符串直接搜这些关键词,有结果就是有人在尝试注入
扫描漏洞短时间内大量404请求,访问各种不存在的路径比如/wp-admin/setup-config.php/.env/phpmyadmin/
Webshell访问访问一些奇怪的PHP文件路径,比如/wp-content/uploads/shell.php这些路径不是正常WordPress会有的
爬虫/采集同一IP短时间内大量GET请求,访问所有文章页面看UA——如果是正常蜘蛛会标明自己是Googlebot或Baiduspider

暴力破解是最常见的。 我之前那个站,日志里80%的异常请求都是暴力破解。攻击者会用一些常见的用户名密码组合(admin/123456、admin/admin、test/test)来试,试成功了就进来了。

这里有个很多人不知道的点:如果攻击者尝试登录,但密码不对,状态码也是200,不是401。 WordPress的登录页面,不管登录成功还是失败,返回的状态码都是200。所以你不能只看状态码,要结合频率和IP来判断。

其实就是一句话:正常人的访问行为是有节奏的,攻击者的行为是机器式的。 一旦你在日志里看到那种机械重复的模式,十有八九不正常。


怎么用命令快速翻日志(不用一条条看)

日志文件动不动就几百MB,一条条看是不可能看完的。我用几个命令就能快速定位问题。

看最近500条日志:

tail -n 500 /www/wwwlogs/你的域名.log

看某个IP的所有访问记录:

grep "178.128.xxx.xxx" /www/wwwlogs/你的域名.log

统计访问最多的IP(找出可疑IP):

awk '{print $1}' /www/wwwlogs/你的域名.log | sort | uniq -c | sort -rn | head -20

搜有没有人在尝试SQL注入:

grep -i "union select\|' or '1'='1\|drop table" /www/wwwlogs/你的域名.log

统计POST请求(找出谁在频繁提交表单):

grep "POST" /www/wwwlogs/你的域名.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

这几个命令,我平时至少每周跑一次。特别是最后一个统计POST请求的,跑一下就能看到最近谁在频繁往你的网站发数据。如果某个IP的POST请求数量远超其他IP,那就要重点关注了。


发现异常之后怎么办

找到了可疑IP和攻击行为,接下来就是处理。

第一步:封IP。 如果用的是宝塔,直接在”安全”里把IP加入黑名单。如果用Nginx,可以这样:

# 在Nginx配置里加
deny 178.128.xxx.xxx;

或者在服务器层面用iptables封:

iptables -A INPUT -s 178.128.xxx.xxx -j DROP

第二步:检查有没有被攻破。 封了IP之后,回头确认一下攻击者的尝试有没有成功。如果日志里发现了某个POST请求返回了302重定向(登录成功后会跳转),那说明密码已经被猜出来了。这种情况需要立刻改密码,并且排查网站有没有被植入后门

第三步:加固防护。 封IP只是治标,攻击者换个IP又会来。可以做几件事:

  • wp-login.php的访问限制为只有你自己的IP能访问
  • 安装登录限制插件,比如Limit Login Attempts Reloaded
  • 开启双因素认证(WordPress后台安全加固里有详细步骤)

第四步:保留日志。 不要急着删日志。如果后续需要报警或者向服务器商投诉,日志文件就是证据。


日志不是出事了才看,应该定期看

我现在的习惯是:每周一早上花十分钟,跑一下上面那几个命令,看看过去一周有没有异常。大多数时候没什么问题,但偶尔会抓到一个新的扫描IP,及时封掉就没事了。

日志这东西,跟网站备份一样,平时不觉得重要,出了事才会后悔没早点看。我那个被暴力破解两周才发现的血泪教训,后来成了我写这篇文章的起点。如果你现在还没看过自己的网站日志,今天花十分钟去看一眼——可能什么都没有,也可能你会发现一个跟我一样的问题。


原创文章,首发于 wujianzhan.com。