软件世界是建立在信任之上的:用户相信程序,程序相信数据,系统相信环境。 然而,只要存在输入、网络、用户与攻击者,这种信任就随时可能被打破。
下面总结了程序员必须了解的 十大网络安全风险。它们并不神秘,但都极其常见。一旦发生,会直接影响系统的可靠性、数据安全以及用户信任。
1. SQL 注入(SQL Injection)
SQL 注入是最经典也最基础的安全问题。 只要 SQL 是通过字符串拼接生成的,就可能被恶意修改逻辑。
示例:
query = f"SELECT * FROM users WHERE name = '{username}'"
当 username 为:
' OR 1=1 --
SQL 将变为:
SELECT * FROM users WHERE name = '' OR 1=1 --'
结果就是把整张表都查出来。
防御方式:
- 使用参数化查询(Prepared Statement)
- 永远不要用字符串拼接构造 SQL
2. 跨站脚本攻击(XSS)
XSS 的本质是:用户输入的内容被当作脚本执行了。
例子:
<div>{{ nickname }}</div>
如果昵称是:
<script>alert('XSS')</script>
页面就会执行这段代码。
后果可能是窃取 Cookie、篡改页面、发起恶意请求等。
防御方式:
- 输出前进行 HTML 转义
- 使用默认防御 XSS 的模板引擎(React/Vue 等)
3. 跨站请求伪造(CSRF)
CSRF 的特点是:用户在登录状态下,被诱导访问某个恶意页面,然后浏览器自动携带 Cookie,导致后台执行了用户并未授权的操作。
例如:
<img src="https://bank.com/transfer?to=hacker&amount=5000">
只要用户登录过银行网站,这个请求就可能执行。
防御方式:
- 使用 CSRF Token
- 设置 Cookie 的 SameSite 属性
- 对敏感操作要求二次确认
4. 弱密码与密码泄露
很多攻击并不依赖技术漏洞,而是依赖人类弱点。
弱密码(如 123456、password)被暴力破解是十分常见的。
另一个问题是服务器端存储明文密码,一旦数据库泄露,就是灾难。
防御方式:
- 要求使用复杂密码
- 存储密码时使用强哈希算法(bcrypt / argon2)
- 支持双因素认证(2FA)
5. 明文传输(HTTP)
HTTP 是明文的,任何中间节点都可以看到所有内容,包括账号密码。 在公共 WiFi 下尤为危险。
防御方式:
- 全站使用 HTTPS
- 不要将敏感数据暴露在 URL 查询参数中
6. 未授权访问(Broken Access Control)
这是后端最容易忽视的问题。 比如:
/admin/listUsers
如果后台只检查用户是否“已登录”,但不验证用户是否“管理员”,就会造成权限绕过。
防御方式:
- 所有敏感接口都必须进行权限检查
- 不要依赖前端控制权限
7. 文件上传漏洞
文件上传听起来很常见,但风险也极高。
例如:
- 攻击者上传一张看起来是
.jpg的文件,但实际上内部包含可执行代码 - 上传目录允许执行脚本文件
一旦成功,攻击者可以直接控制服务器。
防御方式:
- 校验文件的 MIME 类型而不是文件扩展名
- 上传后重新命名文件
- 将文件放在不可执行目录
- 对图片进行重新编码以确保其内容安全
8. 暴露的管理接口
很多框架在开发模式下会暴露调试接口,例如:
/debug
/swagger-ui
/actuator
如果在生产环境中忘记关闭,就会造成极大的安全风险。
防御方式:
- 生产环境关闭不必要的管理端口
- 必须暴露的端点需要权限认证
- 不在页面上输出敏感系统信息
9. 依赖与供应链攻击
现代开发高度依赖第三方库。 如果依赖包本身含有恶意代码(或被入侵),攻击者就能“曲线入侵”你的系统。
典型方式包括:
- 伪装成相似名字的库
- 在常见库中加入恶意更新
- 泄露依赖版本导致漏洞被利用
防御方式:
- 定期更新和扫描依赖
- 锁定依赖版本
- 只使用可信来源的包
10. 日志与调试信息泄露
日志里常出现敏感数据,例如:
Login failed: username=alice, password=secret
一旦日志泄露,相当于主动暴露系统内部状态。
数据泄露事件中,日志泄漏占比相当高。
防御方式:
- 不记录密码、Token、身份证号等敏感数据
- 控制日志访问权限
- 在生产环境关闭过度详细的调试信息(如 stack trace)
总结
安全风险的根源往往不是复杂的攻击,而是我们理所当然的假设。
一个稳健的系统应该具备:
- 不信任任何输入
- 不依赖客户端安全
- 不暴露内部实现
- 对敏感数据尽量减少存储
- 始终假设攻击者存在
掌握这十大安全风险,可以帮助程序员在设计和构建系统时提前预判问题,减少代价高昂的“线上事故”。