网络安全一直是互联网发展过程中的一个重要问题,随着互联网的普及和应用,越来越多的网站被开发出来,但同时也伴随着越来越多的安全漏洞。本文将介绍一些常见的网站安全漏洞,以及如何避免这些漏洞对网站造成的潜在威胁。
本文是对青训营课程《网站常见安全漏洞》的记录和总结。
常见安全漏洞 - 服务端
第三方依赖漏洞
第三方依赖是指应用程序中使用的第三方库或框架,事实上,现代的应用程序中几乎都会使用第三方依赖,第三方依赖在项目中的占比远超自己编写的代码。
第三方依赖漏洞是指应用程序中使用的第三方依赖存在安全漏洞,攻击者可以利用这些漏洞来攻击应用程序。第三方 依赖漏洞也可能存在于客户端中。
例子:
Apache Log4j2是一个Java日志组件,它是Java应用程序中常用的日志框架之一。在漏洞被修复之前,由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。
「 Apache软件基金会分配了最大CVSS Log4Shell 的严重等级为10,因为数百万台服务器可能容易受到该漏洞的攻击。」
防范:
- 使用安全可靠的第三方依赖,避免使用不安全的第三方依赖。
- 使用依赖安全漏洞扫描工具,及时发现并修复依赖中的安全漏洞。
Github Dependabot 报告依赖漏洞:
SQL注入
攻击者通过在上传的数据中注入 SQL 语句,如果服务端没有对用户输入的数据进行过滤和检查,或者对 SQL 静态模板和动态数据没有严格区分,这段注入的 SQL 语句就可能会被执行,从而导致数据库被攻击者控制,或者泄露数据库中的数据。
例子:
假设服务端拼接 SQL 语句的代码如下:
const sql = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`
攻击者可以通过在用户名和密码中注入 SQL 语句,从而绕过用户名和密码的验证,例如:
const username = `admin' -- `
这样拼接出来的 SQL 语句就变成了:
SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'xxx'
这样就绕过了密码的验证,从而登录到了系统中。
防范:
- 尽可能使用参数化查询,而不是拼接 SQL 语句。使用ORM框架,例如Sequelize、GORM等,可以有效避免SQL注入。
- 注意所使用框架的特性。
- 在需要拼接 SQL 语句的时候,对用户输入的数据进行过滤和检查、对特殊字符进行转义。
类似 SQL 注入的还有命令注入执行等,类似的,也可以通过对用户输入的数据进行过滤和检查、对特殊字符进行转义、设置白名单等来避免这些漏洞。
越权漏洞
越权漏洞是指攻击者通过修改请求参数、伪造请求等方式,绕过服务端的权限验证,从而获取到未授权的资源或者执行未授权的操作。
越权包括未授权越权、水平越权和垂直越权。水平越权是指攻击者获取到其他用户的资源或者执行其他用户的操作。垂直越权是指攻击者获取到高权限用户的资源或者执行高权限用户的操作。
例子:
假设服务端提供如下接口:
GET /resource/:id
用于获取指定id的资源,但是没有对用户进行权限验证,攻击者可以通过遍历 id 的方式,获取到其他资源,特别是在 id 长度较短、自增的情况下,攻击者可以很容易地获取到其他用户的资源。
防范:
- 对用户进行权限验证,避免未授权的用户获取到未授权的资源或者执行未授权的操作。
- 防范垂直越权时,将不同用户组API的中间件分离。
SSRF 服务端请求伪造
SSRF(Server-Side Request Forgery)是指攻击者通过修改请求参数,伪造请求等方式,使得服务端发起了攻击者指定的请求。
例子:
系统支持用户选择在线图片作为头像,用户可以通过输入图片的 URL 地址来设置头像。服务端会将用户输入的 URL 地址作为参数,发起 HTTP 请求,获取图片资源,然后保存到系统中。
攻击者可以通过输入可能的内网地址,从而使得服务端发起了攻击者指定的请求,例如:
http://example.com/api/avatar/upload?url=http://localhost:8005
这样攻击者就可能获取到内网的资源。
防范:
- 设置白名单,避免服务端发起了攻击者指定的请求。
- 对host的ip进行判定,过滤掉内网ip。
文件上传漏洞
文件上传漏洞是指攻击者通过上传恶意文件,从而获取到服务器的权限,或者获取到服务器中的敏感信息。或者恶意使用服务器的资源,例如上传大文件,达到薅羊毛的目的。
防范:
- 限制上传文件的类型和大小。
- 站库分离,将上传的文件保存到其他服务器中。
- 对上传的资源的访问进行限制,例如限制访问身份等。
常见安全漏洞 - 客户端
开放重定向
开放重定向是指攻击者通过构造恶意的 URL 地址,使得用户在访问该 URL 地址时,被重定向到攻击者指定的地址。进行钓鱼、诱导用户下载恶意软件等。
例子:
假设访问/redirect?url=时会发生重定向,攻击者可以构造如下的 URL 地址:
http://example.com/redirect?url=http://evil.com
这样用户在访问该 URL 地址时,就会被重定向到http://evil.com,误以为当前访问的仍是可行的网站。
防范:
- 对重定向的 URL 地址进行白名单过滤,避免重定向到攻击者指定的地址。
- 在重定向时提醒用户。
XSS 跨站脚本攻击
XSS(Cross-Site Scripting)是指攻击者通过在网页中注入恶意脚本,从而获取到用户的敏感信息,或者获取到用户的权限,或者恶意使用用户的资源。
XSS 分为反射型 XSS、存储型 XSS 和 DOM 型 XSS。
非持久型/反射型 XSS 是指攻击者构造恶意的 URL 地址,用户在访问该 URL 地址时,恶意脚本被发往服务器,服务器传回注入了恶意脚本的网页,用户在访问该网页时,恶意脚本被注入到了网页中执行。
持久型/存储型 XSS 是指攻击者将恶意脚本存储到了服务端,用户在访问该网页时,恶意脚本从服务器上传回执行。
DOM 型 XSS 和反射型 XSS 类似,攻击者构造恶意的 URL 地址,用户在访问该 URL 地址时,恶意脚本被注入到了网页中执行。但是恶意脚本只是依靠 DOM 的变化插入到网页中,而不会经过服务器。
例子:
客户端代码:
const name = new URLSearchParams(window.location.search).get('name')
document.getElementById('name').innerHTML = name
攻击者可以构造如下的 URL 地址:
http://example.com/user?name=<img src="err" onerror="alert(document.cookie)">
这样用户在访问该 URL 地址时,就会弹出当前用户的 cookie 信息。
防范:
- 对用户输入的数据进行过滤和检查、对特殊字符进行转义。
- 在将用户输入的数据插入到 HTML 中时,使用
innerText而不是innerHTML。 - 设置
Content-Security-Policy,限制脚本的执行。
CSRF 跨站请求伪造
CSRF(Cross-Site Request Forgery)是指攻击者通过诱导用户点击恶意链接,使得用户在访问该请求时,被攻击者利用用户的身份,执行了攻击者指定的操作。
防范:
- 对请求进行验证,例如添加 token。
- 限制某些场景发送第三方cookie,例如设置
SameSite属性。 - 校验 Referer。
点击劫持
点击劫持是指攻击者通过将恶意网页覆盖在正常网页上,诱导用户点击恶意网页,从而执行攻击者指定的操作。
防范:
- 设置
X-Frame-Options,限制网页被嵌入到iframe中。 - 设置
Content-Security-Policy,设置允许网页被嵌入到iframe中的网页。例如frame-ancestors 'self' https://example.com。
CORS 跨域资源共享
CORS(Cross-Origin Resource Sharing)是指浏览器允许网页向其他域名的服务器发起跨域请求,从而获取到其他域名的资源。
在开发者错误配置 CORS 的情况下,攻击者可以通过构造恶意的请求,导致非预期的站点被跨域访问,从而获取到敏感信息。
例子:
对于获取用户信息的接口GET /user/:id,开发者错误地配置了CORS,允许所有域名的网页发起跨域请求。
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Credentials', true)
next()
})
攻击者可以搭建一个恶意的钓鱼网站,通过XHR发起跨域请求,从而获取到用户的敏感信息。
const id = document.querySelector('#id').value
fetch(`http://example.com/user/${id}`, {
credentials: 'include'
})
防范:
- 正确设置跨域白名单,可以在中间件或网关层如Nginx中设置CORS,限制跨域请求。
总结
本文主要介绍了 Web 应用程序中常见的安全漏洞,包括 SQL 注入、XSS 攻击、CSRF 攻击等,并提供了相应的防范措施。
总的来说,Web 应用程序的安全问题是非常重要的,我们应该时刻关注并采取相应的防范措施。在开发 Web 应用程序时,我们应该遵循安全最佳实践,如使用参数化查询来防止 SQL 注入、使用 CSP 来防止 XSS 攻击、使用 CSRF Token 来防止 CSRF 攻击等。同时,我们还应该定期对我们的应用程序进行安全审计,以确保我们的应用程序始终保持安全。