最直接有效的方式是保存网站首页可信哈希并定期校验,首次用 curl -s url | sha256sum 获取基准存入文件,后续用 curl -sfm 10 url | sha256sum 比对,需统一用 https、设可信 ua、禁用 gzip、规避 waf 干扰,并叠加 script 特征扫描与白名单过滤。

用 curl + sha256sum 定期比对首页哈希值
最直接有效的方式是保存网站首页的可信哈希(如 sha256sum),后续每次抓取实时内容做校验。关键不是“检测变化”,而是“确认是否偏离已知干净状态”。
操作要点:
- 首次运行时,用
curl -s http://example.com/ | sha256sum获取基准哈希,存入/etc/webcheck/baseline.sha256 - 脚本中必须加
-f(fail on HTTP error)和-m 10(超时 10 秒),避免因网络抖动误报:curl -sfm 10 http://example.com/ | sha256sum - 注意:HTTP 重定向(301/302)默认会被跟随,若目标站强制跳转到 HTTPS,而你只写了 HTTP 地址,
curl仍会成功返回内容——但实际已不是原始首页。建议统一用https://并加-k(跳过证书验证)仅用于内网或自签场景 - 不要用
md5sum—— 碰撞风险高,且部分恶意注入可能刻意构造 MD5 冲突
识别常见挂马特征:script 标签 + 外链域名
单纯哈希比对能发现篡改,但无法区分是运营更新还是黑产挂马。需叠加文本特征扫描,重点盯住非预期的 <script></script> 行为。
实用检查逻辑:
- 提取所有
<script></script>标签内容及src=属性:curl -sfm 10 https://example.com/ | grep -oE '<script>]*>|src=[^[:space:]]*\.js' | grep -v 'jquery\|bootstrap\|cdn\.jsdelivr\.net'</script> - 特别警惕含
document.write、eval(、unescape(或 base64 字符串的内联脚本 —— 这类几乎全是混淆后加载黑链 - 外链域名若出现
.xyz、.top、.online、cdn-.*\.click等非常规 JS 托管域,基本可判定异常 - 注意:某些 CMS(如 WordPress)会在页脚动态插入统计代码,需把合法域名加入白名单文件(如
/etc/webcheck/whitelist-domains.txt),用grep -vFf /etc/webcheck/whitelist-domains.txt过滤
避免被服务端 UA 过滤或反爬干扰
不少被黑站点同时部署了简单 WAF,会拦截默认 curl 的 User-Agent,导致脚本始终拿到 403 或空白页,误判为“未篡改”。
绕过要点:
- 显式设置可信浏览器 UA:
-H "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36" - 禁用 gzip(某些老 WAF 对
Accept-Encoding: gzip处理异常):--compressed不要加,改用-H "Accept-Encoding: identity" - 如果目标站启用了 Cloudflare 或类似防护,
curl单次请求大概率失败 —— 此时哈希比对失去意义,应改用带基础渲染能力的方案(如chromium --headless --dump-dom),但会显著增加资源开销 - 务必在脚本开头加
set -e和set -o pipefail,否则curl失败后grep仍可能返回 0,掩盖真实错误
日志与告警必须分离输出,且保留原始 HTML 片段
只发一封“首页异常”的邮件毫无排查价值。真正有用的脚本,要在发现不一致时,自动保存当前 HTML 到带时间戳的文件,并高亮差异行。
实操建议:
- 用
diff -u比对原始 baseline HTML 和新抓取内容,输出到/var/log/webcheck/diff-$(date +\%Y\%m\%d-\%H\%M).log - 告警邮件正文里,只放前 3 行
<script></script>匹配结果 + 差异行上下文(用grep -A1 -B1 'document\.write'),避免整页 HTML 塞进邮件触发过滤 - 切勿把敏感信息(如管理后台路径、API key 注释)写死在脚本里;配置项(URL、白名单、收件人)全部抽到外部
/etc/webcheck/config.sh,用source /etc/webcheck/config.sh加载 - 最容易被忽略的是时区和 crond 的 PATH —— 测试时用
env | grep PATH看 cron 环境,脚本里显式写全路径:/usr/bin/curl、/usr/bin/sha256sum











