测试管理 干货分享|安全测试起航之旅

CloudwiseAPM · 2016年11月09日 · 最后由 恒温 回复于 2016年12月01日 · 3059 次阅读

安全测试是在 IT 软件产品的生命周期中,特别是产品开发基本完成到发布阶段,对产品进行检验以验证产品符合安全需求定义和产品质量标准的过程。一句话总结,安全测试就是检查产品是否满足安全需求的过程。

众所周知软件测试分为四大类型,分别是:功能测试、自动化测试、安全测试和性能测试,而安全测试是在功能测试和自动化测试之后,性能测试之前执行的,以免安全测试后修改的一些问题会影响性能。

安全测试的内容通常包括跳过权限验证、修改提交的请求信息等等,复杂一些的产品还要进行 SQL 注入,跨站点脚本之类的测试,下面我们来看看安全问题对于互联网产品的威胁。

SQL 注入

由于程序员的水平及工作经验参差不齐,相当一大部分程序员在编写程序的时候对用户输入数据的合法性没有进行判断,就给应用程序带来一定的安全隐患,用户可以通过提交一段数据库查询代码,在得到的结果中分析出他想要的数据,这就是所谓的 SQL Injection,即 SQL 注入。

对于一个产品或网站来说,如果缺少安全性测试,攻击者可能会通过 SQL 盲注等方法直接暴库(获取所有的数据库)或是获取当前项目所使用的数据库名称、Web 应用使用的账户、表、表结构、字段名甚至数据库中存储的数据内容等,这就是为什么我们的底层连接数据库代码要用一些防 SQL 注入技术的原因了。
SQL 注入是从正常的 WWW 端口访问,而且表面看起来跟一般的 Web 页面访问没什么区别,所以目前市面的防火墙都不会对 SQL 注入发出警报,如果管理员没查看服务器日志的习惯,可能被入侵很长时间都不会发觉。

展示一个最基本的漏洞:

某个系统登录页面,按照如图方式输入用户面密码后点击登录,结果登录成功了,为什么呢?
登录模块的经典 SQL 为:

select id from user where uname=’+ username + ’and pwd=’+ password+’

假如用户名为 admin,密码为 123456 的用户登录该系统,那么登录时所产生的 SQL 语句如下:

select id from user where uname=’admin’and pwd=’123456’

而如果照图中的所示恶意输入的话,该 SQL 就变成如下所示:

select id from user where uname='admin'and pwd=''or'1=1'

或者来个更简单的直接把用户名输入成:admin‘—

这样就以管理员的方式登录进去了或者以 uname 用户成功登录,对于 SQL 解析器来说,这是一个可以被解析并且可以被执行的 SQL 语句。
我们知道 mysql 代码的注释是用—来表示的,若我们变一下上面的 SQL 语句:

select id from user where uname=''or'1=1';drop table user ;--'and pwd=''

如上红色部分是我们的输入,这样我们的 SQL 仍然可以被正确解析,导致 user 表被删除(如果有删除表权限的话);如果没有删除表权限的话也没关系,我们可以用 delete from user 删除整张表的数据来代替删除整张表的效果。

当然,根据 SQL 需要的参数类型不同,所需的注入参数类型也不同,一般判断某一参数点是否存在 SQL 注入的话可以用如下两种方式:

1.在参数后面直接加 ‘来观察是不是报错,如果发现数据库报内部错误,则可以断定有 SQL 注入的问题。

2.如果参数类型是 int 型,可以用 and 1=1;and 1=2 来判断,如果 and 1=1 可以搜索出来,而 and 1=2 搜索出来的结果为 null 或报错,那么我们认识存在 SQL 注入漏洞,因为如果 and 1=1 和 and 1=2 没有被打入系统的话,两个返回值应该与原始值一致,如果两个都被完全当做字符打入系统两个返回值应该都是空,如下图 1;对于 String 类型来说,我们可以用’and ‘1’=’1 以及 ‘and ‘1’=’2 来的判断,如下图 2,道理与 int 类型一样。如果是搜索型参数的话可以用 ‘and’%’ 来注入,如下图 3.根据实际遇到的情况不同需要有意识的去分析需要注入的参数,从而得到注入语句。

确定了 SQL 注入漏洞的存在,作为测试人员可以将这个漏洞报给开发人员进行修复,但作为安全爱好者我们可以做的更多。最基本的方式是使用简单的 SQL 语句去猜解表名及字段名,确认表名的方法可以用 and true ,and false 的方式来判断,如:and(select count(*) from user)>0 返回为空 证明 user 表存在,返回与原始页面一致,则证明不存在;还有确认字段的方法,如:and (select count(username) from user)>0;我们来重点说说确认字段值的方法,这块挺好玩的。

咱们以字符型来举个例子,假如有 username 字段,首先你要知道字段值的长度是多少,用如下语句:

and (select length(username) from users where id=1)=1~10
其次,需要找出每一位上面的字母(a-z A-z 0-9)
and substr ((select usernname from users where id=1),1,1)='a'--'z'
当然也可以用 ASCII 的方法:
and (select ASCII(substr (username,1,1)) from users where id=1)=0~128

来看个实例:

1.先获取长度,通过 burpsuite 工具拦截有 sql 注入的请求,对图中高亮处进行参数化,获取到的 name 字段值长度为 4;

2.再对应获取 name 字段值的每一位,然后分别把获取到的每一位对应 ASCll 码中的值(参数化时是 0~128)找出来就可以了。

字符的方式参数化时 a~z A~Z 0~9,设置这些就可以了。

有时候开发人员会有意识的执行某种输入过滤以防止攻击者输入如’.selecet 等字符,下面来看下怎么避开过了字符:

3.使用 ASCII 码动态构建替代,如在输入中单引号被屏蔽,我们可以尝试使用字符的 ASCII 码代替:CHAR (39)。

4.如果 select 关键字被屏蔽,尝试使用 URL hex 编码:

%00SELECT
%53%45%4c%45%43%54

有些开发人员可能会过滤 Select、Update、Delete 这些关键字,但偏偏忘记区分大小写,大家可以用 selecT 这样尝试一下。在猜不到字段名时,不妨看看网站上的表单,一般为了方便字段名都与表单的输入框取相同的名字。

特别注意:地址栏的 + 号传入程序后解释为空格,%2B 解释为 + 号,%25 解释为% 号,还有就是用 Get 方法注入时,IIS、Apache 等 Web 服务器会记录你提交的所有字符串,而对 Post 方法则不做记录,所以能用 Post 的网址尽量不用 Get。

不过使用透视宝产品的同学就不用有此顾虑啦,因为透视宝底层连接数据库的代码已经用了一些防 SQL 注入的技术,大可放心使用!

权限控制的危害

接下来说说权限控制,权限就好像公司的门禁,只有带了门禁卡的同学才可以随便进出,而没有门禁的人虽然可以出去,但是安全的公司只能让里面的同学开门或别人刷卡才允许进来,这就是最简单的权限。如果少了安全性的保障,那么就会有一些人跳过权限去做一些他们不该做的事情。

举个简单的例子,一个登陆模块只有输入注册过的用户名密码才能登录成功,然后我们就老老实实的输入我们自己注册过的用户名密码(如 abc@baidu.com /123 ),然后就可以登陆成功了。然而假如我们输入一个不存在的用户名呢?

先来看个 SQL,登录模块到数据库对比用的是如下 SQL:

    select count(*) from user where uname="abc@baidu.com" and pwd=“123”

当然实际应用中的 SQL 会比这个复杂的多,若在 SQL 后边加一些特殊的字符串 ‘ or '1=1 其结果会是什么样呢?

    select count(*) from user where uname=" abc@baidu.com " and pwd=“” or "1=1"

我们成功的绕过登录权限认证了……说好的只有注册过的用户才能登录的呢?!……感觉再也不相信爱了有木有……

访问控制大体可以分为三大类:垂直访问控制、水平访问控制和上下文相关访问控制。如果想证明一个电商系统没有权限问题,需要验证以下几点:

第一,登录是否可以不经授权,也就是说有些请求本来是需要登录后才能访问的请求,结果在没有登录的情况下直接访问该请求时也能访问成功;

第二,有无越权问题,比如普通用户是否可以访问只有管理员用户才能访问的请求,如果可以说明存在越权的安全漏洞;

第三,如用户 A 和用户 B 同属于普通用户,每个人的访问请求差不多,但显示的内容会不一样,这时可以看看 B 是否能看到只有 A 才有权限看的内容;

第四,有些功能需要分段操作才能成功,例如找回密码功能,要先输入用户账号,再通过回答各种密保问题,最后才能到获取密码,这时候如果某一步没有做好权限控制,就可能导致应用忽略之前的验证结果而直接执行当前阶段问题;

第五,基于 Referer 消息头的访问控制,尝试执行一些获得授权的特权操作,并提交一个缺少 Referer 消息头或其被修改的请求,如果这种改变导致应用程序阻止请求,应用程序很可能以不安全的方式使用 Referer 消息头。这样继续尝试使用一个未通过验证的用户账户执行相同操作,但提交原始的 Referer 消息头,确认系统是否能够成功执行该操作,有可能获取管理员权限。

接下来说说修改提交数据内容,比如我们上某宝买一个肾 8,需要支付金额 10000 RMB,支付的时候通过工具拦截支付请求,修改金额为 1 RMB ,提交后发现竟然支付成功了。OMG!喜欢苹果的小朋友再也不用担心自己的肾了,哈哈。这些都是因为代码里只在前端做了验证,而后端没有做二次验证所导致的漏洞,透视宝产品几乎所有的验证都是在后端做验证,所以压根就不用担心会出现客户端绕过的漏洞啦。

跨站脚本的安全隐患

最后简单说说跨站脚本的安全隐患,跨站脚本攻击 (Cross Site Scripting,简称 XSS) 是一种经常出现在 Web 应用中的计算机安全漏洞,它允许恶意 Web 用户将代码植入到提供给其它用户使用的页面中,用户在观看网页时恶意脚本就会执行。这类攻击通过注入 HTML 或 js 等脚本发动,攻击成功后攻击者可以得到私密网页内容和 Cookies 等,最近几年 XSS 攻击已经成为最流行的 Web 攻击方式。

XSS 主要分成三大类:

1.反射式 XSS:不存储到数据库中,直接通过页面 302 跳转显示到页面的,仅在页面上及时显示恶意脚本,测试方法是、;

2.存储式 XSS:存储到数据库中,然后从数据库中读取出来显示到页面上;

3.基于 DOM 的 XSS:不保存到数据库也不与后台发生请求关系,只在 dom 或 js 上。

XSS 的危害包括盗取各类用户帐号(机器登录帐号、用户网银帐号、各类管理员帐号),控制数据(包括读取、篡改、添加、删除企业敏感数据的能力),盗窃企业重要的具有商业价值的资料,非法转账,强制发送网站挂马,控制受害者机器向其它网站发起攻击等……

举个存储式 XSS 漏洞的例子,在一个交友网站上有人在个人信息里写了一段脚本,如:

而该网站没有对该段内容进行正确编码,那么网站其他用户看到这个用户信息页时,就会将当前的 cookie 提交到该用户的 web 站点上。

关于 xss 漏洞的资料大家自己可以在网上搜索了解,我这了就不仔细描述啦~

CSRF 跨站请求伪造

既然说到 XSS,那么顺便把 CSRF 也简单说下吧,CSRF(Cross-site Request Forgery)是跨站请求伪造的意思,也被称为 “one click attack” 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种对网站的恶意利用。尽管听起来像跨站脚本 (XSS),但它与 XSS 非常不同,并且攻击方式几乎相左。

XSS 利用站点内的信任用户 (受害者),而 CSRF 通过伪装来自受信任用户的请求来利用受信任的网站,通过社会工程学的手段 (如通过电子邮件发送一个链接) 来蛊惑受害者进行一些敏感性的操作,如修改密码、修改 E-mail、转账等,而受害者还不知道他已经中招。

CSRF 的破坏力依赖于受害者的权限,如果受害者只是个普通的用户, 则一个成功的 CSRF 攻击会危害用户的个人数据以及一些功能;如果受害者具有管理员权限,则一个成功的 CSRF 攻击甚至会威胁到整个网站的安全。与 XSS 攻击相比,CSRF 攻击往往不太流行 (因此对其进行防范的资源也相当稀少) 和难以防范,故被认为是比 XSS 更具危险性的,所以 CSRF 在业内有个响当当的名字——沉睡的巨人。

举个典型的 CSRF 例子:

Alice 登录了某金融网站 mybank.com 准备进行网上支付,Bob 知道这个金融网站并且意识到这个站点的转账功能有 CSRF 漏洞,于是 Bob 在 myblog.com 上发表了一条日志,这个日志支持 img 自定义功能,Bob 插入了这么一行 HTML 代码:

Alice 在自己的浏览器上打开了另一个标签页正好读到这个页面,于是 Alice 的账户就不知不觉地向 Bob 的账户转账 3000 元,而她却毫不知情。
本次分享就先到这里吧,只是启蒙下,详细的过程以后有机会再给大家一一介绍,谢谢~

共收到 6 条回复 时间 点赞

介绍的很详细啊,我们团队最近也在做服务端安全相关的,也涉及到 SQL 注入。刚好能 get 到 point,如果把格式调整一下就更好了

赞赞赞,说明很细致

匿名 #3 · 2016年11月16日

SQL 注入,讲的不错

支持分享啦

楼主,文章请使用 markdown 排版

楼主,文章请使用 markdown 排版

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册