技术开发 频道

如何进行验证测试

  【IT168 评论】所谓认证,就是建立确信某物或某人是真实的这么一个过程,authentication来自于希腊语,即真实的,可信的。认证本身依赖于多个认证因子,在计算机安全领域,认证意味着验证通讯发起者的数字身份,常见的认证过程就是用户登录认证,所谓认证测试就是理解系统中的认证机制并找到方法绕过该认证机制。

  认证测试需要考虑的点有很多,下面我们逐一来进行解释说明:

   在加密通道上传递密码

  原则上,用户的认证必须通过加密信道进行传输,我们在这里的目的不是要验证诸如HTTPS是否安全,我们要验证的仅仅是用户的认证信息是否已经被加密了。

  在用户登录时,最常见的方式是用户输入用户名和密码后,通过POST方法传输,一般来说,认证信息或者是通过不安全的HTTP传递,或者是通过加密的HTTPS传递。我们注意到,甚至有些网站在登录页面显示给我们的是HTTPS,但事实上却仍然是用HTTP的,最简单的方法就是用网络监听工具,如SnifferPro或Ethereal来判断是否是真实加密了。

  下面,我们用OWASP的WebScrab截取一些信息来做个例子

  假设,登录页面要求用户输入用户名和密码,然后有一个“提交”按钮,那么在WebScrab中我们得到如下的请求数据:

  POSThttp://www.example.com/AuthenticationServletHTTP/1.1

  Host:www.example.com

  User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404

  Accept: text/xml,application/xml,application/xhtml+xml

  Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

  Accept-Encoding: gzip,deflate

  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

  Keep-Alive: 300

  Connection: keep-alive

  Referer:http://www.example.com/index.jsp

  Cookie: JSESSIONID=LVrRRQQXgwyWpW7QMnS49vtW1yBdqn98CGlkP4jTvVCGdyPkmn3S!

  Content-Type: application/x-www-form-urlencoded

  Content-length: 64

  delegated_service=218&User=test&Pass=test&Submit=SUBMIT

  在上面的数据中,我们可以看到,POST方法通过HTTP协议把数据发送到http://www.example.com/AuthenticationServlet,那么显然在这时,传送的数据没有进行加密,恶意用户通过监听网络就很容易得到用户名和密码。

  再看下一个例子,假设是用HTTPS协议,那么请求的头数据如下:

  POST https://www.example.com:443/cgi-bin/login.cgi HTTP/1.1

  Host: www.example.com

  User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404

  Accept: text/xml,application/xml,application/xhtml+xml,text/html

  Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

  Accept-Encoding: gzip,deflate

  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

  Keep-Alive: 300

  Connection: keep-alive

  Referer: https://www.example.com/cgi-bin/login.cgi

  Cookie: language=English;

  Content-Type: application/x-www-form-urlencoded

  Content-length: 50

  Command=Login&User=test&Pass=test

  可见,上述例子中的数据经加密后被传送到https://www.example.com:443/cgi-bin/login.cgi,这就确保了数据是加密的而不被其他人所窃取。

  再看下面的一个例子,我们在一个可以通过HTTP协议访问到的页面上通过HTTPS协议来发送数据:

  POST https://www.example.com:443/login.do HTTP/1.1

  Host: www.example.com

  User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404

  Accept: text/xml,application/xml,application/xhtml+xml,text/html

  Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

  Accept-Encoding: gzip,deflate

  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

  Keep-Alive: 300

  Connection: keep-alive

  Referer: http://www.example.com/homepage.do

  Cookie: SERVTIMSESSIONID=s2JyLkvDJ9ZhX3yr5BJ3DFLkdphH0QNSJ3VQB6pLhjkW6F

  Content-Type: application/x-www-form-urlencoded

  Content-length: 45

  User=test&Pass=test&portal=ExamplePortal

  如上,我们看到,我们的请求通过HTTPS引向了https://www.example.com:443/login.do,但如果我们再看Referer的值,就发现我们是从HTTP页http://www.example.com/homepage.do过来的。在这种情况下,我们的浏览器窗口中并不会告诉我们现在使用的安全连接,而事实上我们却正在使用安全连接。

  在上面的例子中,如果我们用Get方法,那么所输入的用户名和密码将会以明文的方式显示在URL中,这显然是不可取的。那么,如果我们经由Get方法通过HTTPS来传递数据是否可行呢,看下面的数据:

  GET https://www.example.com/success.html?user=test&pass=test HTTP/1.1

  Host: www.example.com

  User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404

  Accept: text/xml,application/xml,application/xhtml+xml,text/html

  Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3

  Accept-Encoding: gzip,deflate

  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

  Keep-Alive: 300

  Connection: keep-alive

  Referer: https://www.example.com/form.html

  If-Modified-Since: Mon, 30 Jun 2008 07:55:11 GMT

  If-None-Match: "43a01-5b-4868915f"

  从上面的例子可以看到,用户名和密码都以明文的方式在URL里存在,而不像上面的几个例子中都在消息体中,但并不是说攻击者就可以很容易看到这些信息,TLS/SSL毕竟是安全性很高的协议,整个HTTP数据包是加密的,但仍然要注意的是这些用户名和密码在传输过程中会被存储在代理和服务器上,这也就有可能会泄露用户信息。

   用户列举测试法

  这种测试,简而言之是通过与应用的认证机制的交互,尝试能否获得一些正确的用户名,这对后面我们会讲到的暴力破解很有效,确认了正确的用户名就能用暴力破解去尝试密码了。

  通常,WEB应用对于用户名正确的输入会有一些信息反馈,例如,如果我们输错了密码,那么有时会反馈告知我们系统存在该用户,或密码错误。所以,作为测试人员,就要尝试不同的请求来判断系统是否会有不同的返回。

  对于HTTP的响应消息测试:

  ◇ 输入正确的用户名和密码

  期望结果:使用WebScrab抓取服务器的返回信息(HTTP 200 Response,消息的长度)

  ◇ 输入正确的用户名/错误的密码

  期望结果:从浏览器我们往往会得到如下的返回

  或者是如下返回

  甚至是如下的返回

  Login for User foo: invalid password

  ◇ 输入不存在的用户名

  期望结果:返回可能如下

  或者是如下的消息

  Login failed for User foo: invalid Account

  通常情况下,对于不同的出错信息,服务器往往返回的消息是一样的,但如果不同,测试人员就要去尝试在什么情况下不同,如下:

  客户请求:正确用户/错误密码——>服务器返回:密码错误

  客户请求:错误用户/错误密码——>服务器返回:用户不存在。

  那么显然第一条就告诉我们我们输入的是正确的用户名,通过这种方式我们就可以获得一些正确的用户名信息。

  还有其他一些尝试列举的方法:

  ◇ 有些应用程序会返回一些特定的出错信息;

  ◇ 分析URL以及重定向URL

  如下面的URL:

  http://www.foo.com/err.jsp?User=baduser&Error=0

  http://www.foo.com/err.jsp?User=gooduser&Error=2

  上面两个URL都告诉我们到了错误页面,但上一条是Error值为0,下一条Error值为2,那么我们可以猜测我们获得了一个正确的用户名。

  ◇ URI探测

  有时候,Web服务器在接受一个对目录访问请求时,根据目录是否存在会有不同的返回信息,例如在某些网站会给每个用户设定一个目录,那么我们如果尝试访问某个已存在的目录时,它可能的返回页面如下:

  403 Forbidden error code

  404 Not found error code

  举例:

  http://www.foo.com/account1-返回的出错信息: 403 Forbidden

  http://www.foo.com/account2-返回的出错信息: 404 file Not Found

  那么显然,account1是现实存在的。

  探测性用户账户测试法

  众所周知,在系统中往往会有默认账户或者很容易被猜到的常用账户,而且往往很多用户会使用默认的密码,同样,有些应用系统的测试账户研发人员有时也会忘记删除。这个问题事实上是一个漏洞,而这种漏洞往往是由于以下原因造成的:

  ◇ 没有经验的IT工程师,他们往往不会更改安装的架构组件的缺省密码;

  ◇ 编程人员在应用中留有后门以便测试,但在发布时忘记删除;

  ◇ 系统的管理员和用户采用了很简单的密码;

  ◇ 系统有内嵌的,无法删除的内部用户名和密码;

  ◇ ……

  对于注入Cisco路由器或WebLogic等,他们都有一些默认的用户名和密码,我们可以直接尝试,对于一些我们根本不了解的应用,我们可以做如下尝试:

  ◇ 尝试以下系统管理员的常用账号——"admin", "administrator", "root", "system", "guest", "operator", "super","qa", "test", "test1", "testing",针对用户名和密码组合尝试,也可以尝试诸如"password", "pass123", "password123", "admin",或guest"这些密码。如果这些都无法成功,我们可以写一些脚本来尝试类似的用户名和密码组合。

  ◇ 管理员的密码有时会与系统名字相关,如我们测试的应用系统叫“Obscurity”,那么可以尝试用户名/密码组合Obscurity/obscurity。

  ◇ 利用注册页面我们也可以猜测用户名和密码的格式和长度。

  ◇ 尝试上述提到的所有用户名和空密码。

  ◇ 查看页面的源文件,尝试找到所有引用到用户名和密码的信息,比如"If username='admin' then starturl=/admin.asp else /index.asp"

  ◇ 寻找那些源文件中注释中可能含有的用户名和密码信息;

  ◇ ……

  强力测试(暴力测试)

  任何一种技术,在不同的人手里运用所达到的效果是不同的,正如暴力测试,也叫暴力破解,安全服务人员和测试人员利用这种技术来验证是否存在漏洞,而攻击者则利用其来寻找漏洞。

  Web应用系统通常会有一些用户认证方式,这些方式包括证书、指纹、一次性令牌等等,但更多的,往往是用户名和密码的组合,这就使得暴力破解成为可能。

  在对Web应用系统做暴力测试时,首先我们需要了解的是系统的认证机制,通常Web系统会采用以下两种机制:

  ◇ HTTP认证——包含基本存取认证和数字存取认证。

  ◇ 基于HTML表单的认证。

  我们下面对这些认证方式做一下简单介绍:

  基本存取认证

  基本存取认证假设假定用户会以用户名和密码的组合来表明自己的身份,当用户浏览器使用这种机制访问站点时,web服务器将会返回一个包含“WWW-Authenticate”头的401响应,且包含了一个“Basic”值,以及被保护的域名(例如,WWW-Authenticate: Basic realm=”wwwProtectedSite”)客户端会弹出一个需要用户输入该域用户名和密码的提示框。然后,客户端浏览器返回给服务器一个响应,响应包含“Authorization”头,还包含“Basic”值以及连接了用户名,冒号,密码的基于64位的编码(例如,Authorization: Basic b3dhc3A6cGFzc3dvcmQ=),但可惜的是,这个回复只要被攻击者监听到就很容易被解码。

  我们来看一下这个过程:

  1. 客户端发送一个标准的HTTP请求

  GET /members/docs/file.pdf HTTP/1.1

  Host: target

  2. web服务器定位到访问的这个资源是在一个受保护的目录;

  3. 服务器发送一个HTTP 401的认证请求;

  HTTP/1.1 401 Authorization Required

  Date: Sat, 04 Nov 2006 12:52:40 GMT

  WWW-Authenticate: Basic realm="User Realm"

  Content-Length: 401

  Keep-Alive: timeout=15, max=100

  Connection: Keep-Alive

  Content-Type: text/html; charset=iso-8859-1

  4. 浏览器弹出要求输入用户名和密码的数据窗口;

  5. 用户输入用户名和密码后,包含以下数据后再次提交;

  GET /members/docs/file.pdf HTTP/1.1

  Host: target

  Authorization: Basic b3dhc3A6cGFzc3dvcmQ=

  6. 服务器把客户信息和存储的信息进行比较;

  7. 如果身份验证正确,服务器发回被请求的内容,如果失败,服务器将会返回HTTP。

0
相关文章