安全
如何检查网站的安全性:被动检查能告诉你什么,不能告诉你什么
花一个下午,你能安全地检查自己网站的哪些安全项,被动扫描工具实际上看的是什么,以及哪些地方必须由人来把关。
本页内容
“我的网站安全吗?”这个问题没有非黑即白的答案,但有一个实用的第一步:先检查你的安全配置中,互联网上任何人都已经能看到的那些部分。每个访问你网站的浏览器都会收到你的 HTTPS 配置、证书、响应头和 Cookie。如果这些配置有误,你就是在平白无故地降低攻击门槛,而修复它们通常只需要改几项设置,不必重写代码。
本指南将逐一说明该检查什么、怎么检查,以及同样重要的一点:这样的检查无法告诉你什么。
被动检查与安全测试的区别
被动检查发出的请求与浏览器发出的是同一类,然后读取返回的结果。它从不发送攻击载荷,从不提交表单,也从不尝试登录。因此,它随时都可以放心地对线上网站运行,并且很擅长找出配置错误。
渗透测试则不同:由具备资质的人员在你的授权下主动尝试入侵,测试登录、输入处理、访问控制和业务逻辑。它能发现被动检查看不到的漏洞,但绝不是可以对着生产环境网站随手一试的事情。
先从被动这一层做起。它很快,而且一个连看得见的基本项都没做对的网站,通常还存在其他问题。
检查什么,以及怎样才算合格
1. 全站 HTTPS,并使用永久重定向
每个页面都应通过 https:// 加载,输入不带加密的 http:// 地址时,应返回 301 或 308 重定向到 HTTPS 版本。302 也能用,但浏览器不会记住它;而仍然通过明文 HTTP 提供页面的网站,会让同一网络中的任何人都能读取或篡改页面内容。可以用 curl -I http://yourdomain.com/ 测试,查看状态行和 Location 响应头。
2. 有效且能自动续期的证书
证书必须受信任、与你的域名匹配,并且没有临近过期。证书过期几乎都是因为续期任务在服务器或 DNS 变更后悄悄停掉了。点击浏览器中的锁形图标可以查看颁发者和到期日期,同时要确保续期是自动进行的。
3. 取值合理的安全响应头
Strict-Transport-Security、Content-Security-Policy、X-Content-Type-Options 和 Referrer-Policy 等响应头用来开启浏览器内置的防护功能。它们的取值和有没有同样重要:测试时遗留下来的 300 秒 HSTS max-age 几乎起不到保护作用,而 script-src 中含有 'unsafe-inline' 或 * 的 CSP 对注入的脚本也没什么防御力。我们的安全响应头和 Content-Security-Policy 指南介绍了哪些取值是安全的。
4. Cookie 标志
会话和登录 Cookie 应设置 Secure(仅限 HTTPS)、HttpOnly(JavaScript 无法读取),并带有明确的 SameSite 值。在浏览器中打开开发者工具,依次查看 Application(Chrome、Edge)或 Storage(Firefox)→ Cookies。如何检查 Cookie 安全性这篇指南逐一讲解了每个标志。
5. 不轻信所有来源的 CORS
跨源资源共享(CORS)响应头告诉浏览器,哪些其他网站可以读取你的响应。危险的做法是:服务器把收到的任意 Origin 原样写进 Access-Control-Allow-Origin,同时还发送 Access-Control-Allow-Credentials: true。这样一来,任何网站都能读取携带你访客 Cookie 发出的请求所得到的响应。应当改为只允许特定的源。
6. 没有混合内容
HTTPS 页面如果通过 http:// 加载脚本、样式表或框架,就存在主动混合内容,现代浏览器会将其拦截,页面往往因此出问题。通过明文 HTTP 加载的图片和媒体属于被动混合内容:危险性较低,但仍会削弱锁形图标所代表的安全性。请在模板和数据库中搜索硬编码的 http:// 网址。
7. 你向攻击者透露了什么
Server: Apache/2.4.41 或 X-Powered-By: PHP/7.4 这样的响应头会把确切的版本公之于众。公开的 JavaScript source map 则可能把你的前端源代码原样暴露出去。两者本身都不算漏洞,但都替攻击者省了时间。另外,可以考虑发布一个 /.well-known/security.txt 文件,写明 Contact 和 Expires 日期,让发现问题的人知道如何联系你。
运行一次被动安全检查
Rudra 的免费安全检测工具只使用 GET 和 HEAD 请求,读取你的 HTTPS 配置、证书、响应头取值、Cookie 标志、CORS 和混合内容。
Rudra 的安全检测工具是怎么做的
免费网站安全检测工具会自动完成上面这份清单。它向你的页面发送一个普通请求,读取响应头、页面设置的 Cookie(只读取名称和标志,绝不读取值)以及 HTML。随后,它会再发出一小组固定的只读请求:一次用于获取证书的 TLS 连接;一次对 http://yourdomain/ 的请求,查看它如何重定向;一次携带虚构测试源(https://rudra-audit.invalid)的请求,查看你的 CORS 响应头如何回应;以及对一份简短白名单中的常见文件(如 security.txt 和 robots.txt)的请求。
每项发现都会显示观察到的值、合格的值是什么样,以及该项检查的置信度。有些写法,比如内联的 onclick 处理程序,或没有使用子资源完整性(Subresource Integrity)的第三方脚本,可能没问题,也可能有风险,要看具体情况,所以它们会以低置信度标出,供你自行判断,而不是当作已确认的问题呈现。报告还会列出它能看到的技术栈和对外暴露面,比如登录表单和页面中提到的 API 网址,让你清楚从外部能看到什么。
被动检查无法告诉你什么
人们往往会在这里对高分作出过度解读。被动检查(包括我们的在内)不会:
- 发现你代码中的漏洞,例如 SQL 注入、跨站脚本或访问控制失效;
- 扫描你的 CMS、插件、库或服务器是否为已知存在漏洞的版本(除非某个响应头恰好暴露了版本);
- 测试登录后才能访问的任何内容,包括管理后台和账户页面;
- 测试表单提交后的行为,包括 CSRF 防护和速率限制;
- 检测恶意软件、页面被篡改或账户被盗用;
- 审查你的主机托管、备份、访问控制,或者管理员密码掌握在谁手里。
检查结果干净,说明看得见的配置状况良好。这并不代表网站在各个方面都是安全的,任何自动化扫描都无法作出这样的保证。
扫描之外还应该做什么
- 及时更新软件。尽快安装 CMS、插件、主题和框架的更新,并删除不用的插件。
- 保护管理员账户。凡是能修改网站的账户,都要使用独一无二的密码和双重身份验证。
- 保留经过验证的备份。从未做过恢复演练的备份只是一种指望,算不上方案。
- 留意变化。每次部署之后,以及每次新增第三方脚本时,都重新运行一次被动检查。
- 风险足够高时,请专业人员来测试。如果你处理支付、健康数据或用户账户,就应当委托具备资质的测试人员,按书面约定的范围进行渗透测试。
至于网站健康状况的其他方面,如速度、SEO、无障碍和失效链接,可以对同一个页面运行一次完整的网站审核。
常见问题
扫描网站的安全问题合法吗?
被动检查读取的是网站发送给每位访客的内容,但你仍然应该只测试自己拥有或已获授权的网站。主动测试(比如尝试攻击载荷或登录)需要得到网站所有者明确的书面许可。
免费的安全检测工具能告诉我网站是否被黑了吗?
不能。配置检查不会查找恶意软件、被注入的垃圾内容或被盗用的账户。如果你怀疑网站已被入侵,请查看主机商提供的安全工具和日志,并寻求专业帮助。
最应该先修复的是什么?
让每个页面都使用 HTTPS,并把 HTTP 永久重定向过去,同时确保证书能自动续期。之后依次是会话 Cookie 标志、HSTS,以及先以仅报告模式上线的 Content-Security-Policy。
安全评分高就说明我的网站安全吗?
它说明看得见的配置是好的:HTTPS、证书、响应头、Cookie 标志和 CORS。至于代码或插件中的漏洞,它什么也说明不了,那需要靠更新、代码审查,风险较高的网站还需要渗透测试。