网站开发人员需要注意的安全事项
一、越权漏洞
越权漏洞是一种很常见的逻辑安全漏洞。可以这样理解:服务器端对客户提出的数据操作请求过分信任,忽略了对该用户操作权限的判定,导致攻击账号拥有了其他账户的增删改查功能。
主要发生在前台系统,这也是开发人员比较容易忽视的地方,前台系统一般都是有数据权限之分。
比如A用户创建了一个订单,订单id为1,当B用户通过更新地址http://localhost/orders/update?id=1,将id为1的数据更新,如果没有进行数据权限的判断,订单id为1的数据将会被B用户修改。
解决方案:对于用户的每一个请求操作都需要对请求的数据和当前用户身份做校验,判断用户请求的数据是否是属于该用户的数据。
二、xss漏洞
XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性。其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的。如,盗取用户Cookie、破坏页面结构、重定向到其它网站等。
XSS防御
在asp.net mvc中已经默认开启了防范xss攻击,在发现提交的数据中包含了XSS攻击的代码,就会抛出异常,只有在特殊情况下允许用户提交html代码时,才会单独开启某个action允许用户提交html代码。
在php中,没有对xss攻击进行处理,需要我们对用户请求数据进行转义或过滤。
三、sql注入漏洞
sql注入通过构建特殊字符作为参数传入到应用程序,而这些字符大都是sql语法里的一些组合,通过执行sql语句进而执行攻击者所要的操作。
对于开发人员如何解决sql注入?
1、对特殊字符转义。
2、不要使用动态拼装sql,而是使用参数化的sql。
例如:
$userCode = "1' or 1='1"; $sql = "select * from users where userCode='{$userCode}'";
就会变成:
$sql = "select * from users where userCode='1' or 1='1'";
当执行这条语句时,会把users表的所有数据查询出来。
如果我们使用参数化,就不会存在这个问题了。
在php中支持sql参数化的组件有:pdo、mysqli,但一般php开源框架都有对这两个组件进行封装,我们可以很方便的去使用参数化sql。
pdo例子:
$userCode = "1' or 1='1"; $stmt = $pdo->prepare('select * from users where userCode=:userCode'); $stmt->execute(array(':userCode' => $userCode));
就会变成:
select * from users where userCode = '1\' or 1=\'1';
这样就只会查询userCode等于“1' or 1='1”的数据了。
四、并发操作
并发操作是指多个用户在同一个时间点请求同一个操作或不同操作但相关联的操作。
并发处理不当会导致脏读、幻读和不可重复读等此类问题。
脏读:
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
不可重复读:
不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
幻读:
例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样。这就叫幻读。
解决并发操作:
在数据库事务中使用锁机制。
在mysql中使用行级锁for update:
select * from users where id = 1 for update;
五、数据库事务
数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。
通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。
一个逻辑工作单元要成为事务,必须满足ACID(原子性、一致性、隔离性和持久性)属性。
数据库事务注意事项:
1、数据库事务要保证要么成功提交事务,要么失败回滚事务,防止占用事务,而不进行提交或回滚。
2、在数据库事务中,不要有耗时的处理,防止造成死锁。
六、浮点数偏差
6.1在.net中
float f = 0.1f; float sum = 0; for (int i = 0; i < 4000000; i++) { sum += f; } Console.WriteLine(sum); double d = 0.1d; double sum0 = 0; for (int i = 0; i < 4000000; i++) { sum0 += d; } Console.WriteLine(sum0); decimal m = 0.1m; decimal sum1 = 0; for (int i = 0; i < 4000000; i++) { sum1 += m; } Console.WriteLine(sum1); Console.ReadKey();
6.2在php中
$f = 0.1; $sum = 0; for ($i = 0; $i < 4000000; $i++) { $sum += $f; } echo $sum."<br/>"; $f = 0.1; $sum = 0; for ($i = 0; $i < 4000000; $i++) { $sum = bcadd($sum,$f,3); } echo $sum."<br/>";
输出结果:
399999.99997867
400000.000
从上面的结果可以看出,普通的加法计算浮点数会失去精度,在php中给我们提供了高精度计算函数。
php处理高精度计算函数:
bcadd — 加法
bccomp — 比较
bcdiv — 相除
bcmod — 求余数
bcmul — 乘法
bcpow — 次方
bcpowmod — 先次方然后求余数
bcscale — 给所有函数设置小数位精度
bcsqrt — 求平方根
bcsub — 减法