常见 Web 安全攻防总结( 三 )

  • 上图中所谓的攻击网站 B,可能是一个存在其他漏洞的可信任的经常被人访问的网站 。
  • 预防 CSRFCSRF 的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的 CSRF 防御也都在服务端进行 。服务端的预防 CSRF 攻击的方式方法有多种,但思路上都是差不多的,主要从以下两个方面入手:
    • 正确使用 GET,POST 请求和 cookie
    • 在非 GET 请求中增加 token
    一般而言,普通的 Web 应用都是以 GET、POST 请求为主,还有一种请求是 cookie 方式 。我们一般都是按照如下规则设计应用的请求:
    • GET 请求常用在查看,列举,展示等不需要改变资源属性的时候(数据库 query 查询的时候)
    • POST 请求常用在 From 表单提交,改变一个资源的属性或者做其他一些事情的时候(数据库有 insert、update、delete 的时候)
    当正确的使用了 GET 和 POST 请求之后,剩下的就是在非 GET 方式的请求中增加随机数,这个大概有三种方式来进行:
    • 为每个用户生成一个唯一的 cookie token,所有表单都包含同一个伪随机值,这种方案最简单,因为攻击者不能获得第三方的 cookie(理论上),所以表单中的数据也就构造失败,但是由于用户的 cookie 很容易由于网站的 XSS 漏洞而被盗取,所以这个方案必须要在没有 XSS 的情况下才安全 。
    • 每个 POST 请求使用验证码,这个方案算是比较完美的,但是需要用户多次输入验证码,用户体验比较差,所以不适合在业务中大量运用 。
    • 渲染表单的时候,为每一个表单包含一个 csrfToken,提交表单的时候,带上 csrfToken,然后在后端做 csrfToken 验证 。
    CSRF 的防御可以根据应用场景的不同自行选择 。CSRF 的防御工作确实会在正常业务逻辑的基础上带来很多额外的开发量,但是这种工作量是值得的,毕竟用户隐私以及财产安全是产品最基础的根本 。
    SQL 注入SQL 注入漏洞(SQL Injection)是 Web 开发中最常见的一种安全漏洞 。可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作,甚至有可能获取数据库乃至系统用户最高权限 。
    而造成 SQL 注入的原因是因为程序没有有效的转义过滤用户的输入,使攻击者成功的向服务器提交恶意的 SQL 查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码 。
    很多 Web 开发者没有意识到 SQL 查询是可以被篡改的,从而把 SQL 查询当作可信任的命令 。殊不知,SQL 查询是可以绕开访问控制,从而绕过身份验证和权限检查的 。更有甚者,有可能通过 SQL 查询去运行主机系统级的命令 。
    SQL 注入原理下面将通过一些真实的例子来详细讲解 SQL 注入的方式的原理 。
    考虑以下简单的管理员登录表单:
    12345<form action="/login" method="POST"><p>Username: <input type="text" name="username" /></p><p>Password: <input type="password" name="password" /></p><p><input type="submit" value=https://www.isolves.com/it/aq/fwq/2021-07-09/"登陆" />

    后端的 SQL 语句可能是如下这样的:
    1234567let querySQL = `SELECT *FROM userWHERE username='${username}'AND psw='${password}'`;// 接下来就是执行 sql 语句... 目的就是来验证用户名和密码是不是正确,按理说乍一看上面的 SQL 语句也没什么毛病,确实是能够达到我们的目的,可是你只是站在用户会老老实实按照你的设计来输入的角度来看问题,如果有一个恶意攻击者输入的用户名是 zoumiaojiang' OR 1 = 1 --,密码随意输入,就可以直接登入系统了 。WFT!
    冷静下来思考一下,我们之前预想的真实 SQL 语句是:
    1SELECT * FROM user WHERE username='zoumiaojiang' AND psw='mypassword' 可以恶意攻击者的奇怪用户名将你的 SQL 语句变成了如下形式:
    1SELECT * FROM user WHERE username='zoumiaojiang' OR 1 = 1 --' AND psw='xxxx' 在 SQL 中,-- 是注释后面的内容的意思,所以查询语句就变成了:


    推荐阅读