注意:文章原创作者:健人卢,转载请注明出处 https://blog.csdn.net/lujianhao_ios/article/details/79733833。
本文中将涉及以下类型的安全漏洞
所有来自用户的输入都可能是有害的。
权控缺失
系统未能正确分配用户的权限,用户能执行超出自己职能范围的操作,这类漏洞称为权控缺失。权控缺失分为两类:
- 平行越权
- 垂直越权
假设有这样一个场景,在一个论坛里张三是版主,而李四和王五只是普通的注册用户。
那这里的权限分级,就应该是这样的。版主位于顶端,因为张三不但可以像注册用户一样进行发帖,回复,留言等功能,同时也有更高的权限,去管理注册用户和帖子。而作为注册用户的李四和王五,则处在第二层。他们拥有同样的角色和权限。但他们彼此之间是分离,也就是李四不应该有权限去查看属于王五的数据和代替王五去进行操作。
垂直越权
如图所示序列图,注册用户李四能够执行版主张三的操作,李四能够删除王五的帖子。
平行越权
如图所示序列图,李四能够执行版主王五的操作,李四能够修改王五的帖子。
在实现具体功能时,许多API依赖于id值或标识值
行为 | 标识 |
---|---|
用户(userid:1)给文章(id:20)评论 | userid = 1, id=20 |
用户(userid:1)查看自己收货地址 | userid = 1 |
用户(userid:1)删除自己文章 | userid = 1 |
许多的id值/标识值,与用户的职能、权限息息相关。若在服务端缺乏对此类参数的验证和权限控制,则会导致越权问题。
解决方案
- 服务端利用不可预测的SessionId来做权限控制和判断,而不是直接使用前端传过来的userid,不要相信前端给的任何数据。
- 对于每个请求,服务端需要明确这个是否需要被保护,对于被保护的请求服务端要拒绝匿名的用户请求。
- 对于被保护的请求,服务器需要分辨该角色被授予了什么样的权限,验证该用户是否有权去执行这个请求操作。
逻辑漏洞
逻辑漏洞通常是由于程序逻辑不严密或逻辑太复杂,导致一些逻辑分支被绕过或处理错误。常见漏洞包括:任意密码修改(没有旧密码验证)、密码找回漏洞、业务数据篡改等。逻辑漏洞的出现易造成账号被盗、免费购物,游戏应用易造成刷钱、刷游戏币等严重问题。
这一类漏洞,涉及的更多是业务场景中的逻辑和流程完整性,还有特殊场景,比如支付场景下,对特殊参数的验证,以及完善的验证过程。在此不方便给出具体的解释案例,但网上有很多类似的逻辑漏洞的案例,以下列举几个:
1、又现刷金币BUG!海岛奇兵双倍兵漏洞百出
http://news.17173.com/z/bb/content/07192016/152133372_1.shtml
2、“黑客”玩家入侵网游系统 狂刷34亿“金币”
http://games.qq.com/a/20160228/000694.htm#p=1
3、掌阅读书App账户密码找回绕过/账户信息泄漏/使用他人账户为自己买书等系列问题
http://www.2cto.com/Article/201502/375463.html
解决方案
- 支付场景中,需要对多个参数进行有效性验证。
- 开发过程中要保证业务逻辑的完整性。
- 权限控制和功能控制不能依赖于服务器的响应,验证过程应该在服务端实现。
条件竞争
服务端在做并发编程时,需要考虑到条件竞争的情况。在多个并发线程同时访问同一资源时,由于对请求的处理不是原子性的,无法预测调度的顺序,就可能由于时间序列上的冲突而造成对共享资源的操作混乱。
假设有这样一个场景,某商城在搞一个活动,用户可以通过积分换取全场通用的现金券。
正常逻辑如下:
- 用户请求兑换代金券的接口
- 读取数据库用户积分余额
- 如果大于300,余额减300,更新数据库余额(update users set balance = balance - 300 where userid=’userid’)
- 返回数据
高并发场景下的用户请求:
模拟高并发场景,利用多线程同时发出3个一模一样的请求,多个请求会同时达到服务端。由于程序处理这些请求有时间序列上的冲突,那么系统在读取用户积分余额的时候,可能会读取到不同的结果。
下图所示系统在处理同时多线程的请求过程:
- 线程1在处理请求时,读取到用户积分余额为500,执行-300的操作,将执行后的结果200存储数据库,然后给用户下发现金券。
- 线程2在处理请求时,在线程1存储200积分前,读取到了用户积分余额500,执行-300的操作,将执行后的结果200存储数据库,给用户下发现金券。(发现线程1和线程2执行了同样的操作,但线程2的操作实际上是有问题的,没有减去实际兑换现金券的300积分)
- 线程3在处理请求时,读取到用户积分余额为200,执行-300操作失败,返回失败。
常见场景
- 活动积分换优惠券
- 使用优惠券下单
- 商城下单购物
- 活动积分转移
- 优惠券领取
- 签到领积分
- 领取红包
解决方案
- 在更新数据库数据时,使用乐观锁。
(错误)update users set balance = balance - 300 where userid=’userid’
(正确)update users set balance = balance - 300 where userid=’userid’ and balance = ‘读到的余额’ - 提交更新时,带上之前读取的数据或状态,于数据库正式对数据的冲突与否进行检测,如果发现冲突了,则返回用户错误的信息。
XSS跨站脚本攻击
是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,提交的数据被WEB应用程序直接使用,使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
XSS跨站脚本攻击可以分成三类:
- 非持久型跨站(反射型)
- 持久型跨站(存储型)
- DOM型跨站
非持久型跨站(反射型)
它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击)。
(简单例子)
正常发送消息:
http://www.test.com/message.php?send=Hello,World
接收者将会接收信息并显示Hello,Word
非正常发送消息:
http://www.test.com/message.php?send=<script>alert(‘foolish!’)</script>
接收者接收消息显示的时候将会弹出警告窗口
持久型跨站(存储型)
它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。谷歌的orkut曾经就遭受到XSS。
(简单例子)
从名字就可了解到存储型XSS攻击就是将攻击代码存入数据库中,然后客户端打开时就执行这些攻击代码。例如留言板
留言板表单中的表单域:
<input type="text" name="content" value="这里是用户填写的数据">
正常操作:
用户是提交相应留言信息;将数据存储到数据库;其他用户访问留言板,应用去数据并显示。
非正常操作:
攻击者在value填写<script>alert(‘foolish!’)</script>
【或者html其他标签(破坏样式。。。)、一段攻击型代码】;
将数据存储到数据库中;
其他用户取出数据显示的时候,将会执行这些攻击性代码
DOM型跨站
DOM文档对象模型,是一种可以用来在浏览器中代表文档的结构格式。DOM 能将动态脚本如JavaScript 提供给文档组件作为参考,例如表单字段或会话cookie。浏览器也可以出于安全考虑使用DOM——例如在为其它域名获得会话cookie 的不同域名中限制脚本。当通过攻击者可以控制的DOM 元素等特制请求修改JavaScript 函数等活动内容时,就说明存在基于DOM 的跨站点脚本漏洞
如果某些 HTML 页面直接使用了 document.location、document.URL 或者 document.referer 等 DOM 元素的属性,攻击者可以利用这些属性植入恶意脚本。
(简单例子)
<HTML>
<TITLE>Welcome!</TITLE>
Hi
<SCRIPT>
var pos=document.URL.indexOf("name=")+5;
document.write(document.URL.substring(pos,document.URL.length));
</SCRIPT>
<BR>
Welcome to our system
…
</HTML>
这个例子是个欢迎页面,name是截取URL中get过来的name参数
正常操作:
http://www.vulnerable.site/welcome.html?name=Joe
非正常操作:
http://www.vulnerable.site/welcome.html?name=<script>alert(document.cookie)</script>
让我们看看:受害者的浏览器接收到这个链接,发送HTTP请求到www.vulnerable.site并且接受到上面的HTML页。受害者的浏览器开始解析这个HTML为DOM,DOM包含一个对象叫document,document里面有个URL属性,这个属性里填充着当前页面的URL。当解析器到达javascript代码,它会执行它并且修改你的HTML页面。倘若代码中引用了document.URL,那么,这部分字符串将会在解析时嵌入到HTML中,然后立即解析,同时,javascript代码会找到(alert(…))并且在同一个页面执行它,这就产生了xss的条件。
解决方案
- 在HTML标签中显示“用户可控数据”前,应该进行html escape转义。下表为需要转义的字符
元字符 | 转义后的字符 |
---|---|
& | & |
< | < |
> | > |
“ | " |
‘ | ' |
/ | / |
- 在JavaScript内容中输出“用户可控数据”,需要做JavaScript Escape转义。
示例代码
<script>alert('#escapeJavaScript($user.name)')</script>
<script>x='escapeJavaScript($user.name)'</script>
在CSS style内容中输出的“用户可控数据”,需要做CSS Escape转义和严格验证。把除了字母、数字外的所有字符都需要被编码成十六进制,形式为“\uHH”。
在URL中输出的“用户可控数据”,需要做URL安全编码。可使用URLEncode,将字符转换成“%HH”的格式。
String q = "random word 500 bank $"
String url = "http://example.com/query?q" + URLEncoder.encode(q,"UTF-8");
- 在XML中输出“用户可控数据”时,对数据部分做HTML转义。示例代码:
<?xml version="1.0" encoding="UTF-8" ?>
《Web安全测试常见漏洞解析(上)》链接地址 https://blog.csdn.net/lujianhao_ios/article/details/79747327