Skip to content


PICT工具使用(Pairwise Independent Combinatorial Testing tool)

PICT工具就是在微软公司内部使用的一款成对组合的命令行生成工具,现在已经对外提供,可以在互联网上下载到。

要把输入类型和其对应的参数输入到一个CSV格式(CSV: 以逗号分割的纯文本文件,不带有任何其他格式。文件使用逗号(,)来分割字段和行。最终文件可以用Excel打开,也可以用做其程序的导入格式。默认情况下,.csv文件将在记事本打开。)

例如:

帐户名: 空,不存在,超长,超短,正常
密码: 空,超长,超短,不匹配,正常
验证码: 空,超长,超短,不匹配,正常
会话: 保存一个月,保存三个月,保存一年,不保存
按钮: 确定,取消

从列表可以看出,有1000多种组合方式。在短时间内对其做测试,将是非常困难的。研究表明,通过PICT,测试用例的数量将大大降低;同时,也可保证很高的测试覆盖率。

如直接通过PICT执行参数文档,测试用例会打印在屏幕上,如下所示:

D:\测试方法\两两测试>pict login.txt

帐户名         密码         验证码  会话                    按钮

不存在          空            不匹配  保存一年             确定

空                 正常          正常     保存一个月         取消

超长            不匹配         空       保存三个月         确定

超短             超短            空       不保存                 取消

超短            空                超长    保存三个月         取消

空                超长          不匹配  不保存                 确定

正常            超短          正常      保存一个月         确定

不存在       不匹配       超短      保存一个月         取消

空                正常          超短      保存一年            确定

超长            超长         正常       保存一年            取消

正常           正常         不匹配     保存三个月      取消

正常           不匹配      超长        不保存              确定

不存在       超长         正常        保存三个月       确定

超短          不匹配      正常        保存一年           确定

不存在      正常          空            保存一个月      确定

超长           空            超短         保存一个月      取消

超短           超长       超短          不保存            取消

正常            空          空              保存一年        确定

超短           超长       空             保存一个月      确定

超短          正常       正常         不保存               确定

空              超短       超短          保存三个月      确定

空             超短        超长          保存一年           确定

正常         超长        超短           不保存             取消

不存在      空          正常            不保存              确定

超长         超短       不匹配        不保存              取消

超短        不匹配     不匹配       保存一个月      取消

超长         正常        超长           保存一个月      取消

空             空            空               保存一个月      确定

空             不匹配    超长           保存一个月      取消

不存在      超短       超长           保存一年          取消

空             超长        超长           不保存             确定

也可把测试用例保存到指定文件中,如下所示:

D:\测试方法\两两测试>pict login.txt > 登录.xls

 

参数文件格式

也称为模型文件。文件中至少包含参数定义。子模型定义及约束定义可选。如下所示:

parameter definitions

 

[sub-model definitions]   

 

[constraint definitions]

例如,上面的登录测试参数文件如下所示:

#登录参数

 

帐户名:空,不存在,超长,超短,正常

 

密码:空,超长,超短,不匹配,正常

 

验证码:空,超长,超短,不匹配,正常

 

会话:保存一个月,保存三个月,保存一年,不保存

 

按钮:确定,取消

其中,#是注释符。注意:参数文件名称需用英文,参数及参数属性的分隔符要用英文字符。

默认情况下,PICT会成对产生测试用例,即按照两两测试原理设计用例。但也可根据实际情况修改参数组合。可通过参数/o实现。

还可根据实际业务,对参数进行限制。例如,如果只有在帐户名、密码、验证码的属性为“正常”时,会话属性才能为“保存一个月”,否则会话属性为“不保存”。参数文件如下所示:

帐户名:空,不存在,超长,超短,正常

密码:空,超长,超短,不匹配,正常

验证码:空,超长,超短,不匹配,正常

会话:保存一个月,保存三个月,保存一年,不保存

按钮:确定,取消

IF [帐户名] = “正常” and [密码]=”正常” and [验证码]=”正常“  THEN [会话] = “保存一个月” ELSE [会话] = “不保存“;

注意:条件语句的结束符为分号。

PICT的条件语句中支持:=、<>、>、>=、<、<=、LIKE、NOT、AND、OR……还可支持参数的互相比较。

         PICT在减少测试用例的数量的同时能保证测试覆盖率。但是如果业务逻辑复杂,需要在参数文件中编写大量的条件判断语句。在实际情况中需综合判断,有需要的可使用此工具。

         总之,微软提供的此款工具功能全面,操作简单。

Posted in 其它.


组合分析法(Combinatorial analysis)

要点:

将多个输入参数进行全排列组合,依据这些组合来设计测试。举个简单的例子,有一个程序需要从1.0升级到2.0,需要让测试工程师模拟不同的测试环境来充分检验这种升级安装过程是否能顺利进行。假设:

  • 需要在Windows 2000/xp/2003 server/vista这4种操作系统上进行测试。
  • 要兼容5种浏览器IE8/7/6/5,Firefox。
  • 操作系统语言要支持三种语言English,German,CHS。
  • 目标机器上可能已经安装了CLR或者还没有安装CLR(假设我们的程序基于.NETFramework 2.0开发)。这是两种情况。

最后将得到4*5*3*2*2=240种可能的组合。

心得:根据错误模型发现,值的互相组合是缺陷的最主要来源,绝大多数缺陷都源于结对参数的组合。由三个或者多个参与的组合而导致的缺陷不占大多数(Very few defects occur in triplet + combination)。

所以,我们可以只专注在成对组合(pair-wise),即以两个两个为主来进行组合设计。首先,每个参数的每种状态都至少测试一次(Each state of each parameter is tested at least once);然后,不同类型中的参数要与其他类型中的参数进行结对测试(Each variable in each parameter is tested in a pair with every variable in other parameters. Pairs of variables test exist in other combinations can be dropped from the matrix of  combinations.)

很明显这种大规模的,不管是全组合还是成对组合,在现实的测试环境下得到的数量都是十分惊人的,而且一次次重复不同的环境组合是一个十分费力和容易出错的工作,基本上无法用手工来完成,所以往往借助工具来生成这种组合。

Posted in 其它.


基于场景的测试方法(scenario testing)

场景,是一种有假设条件的故事,可以辅助我们来把一个复杂的问题或系统像过电影那样地过一遍。我们就像电影导演一样来把整个场景都设想出来。基于场景的测试方法,就是在场景的基础上进行测试。
 
如何能写好基于场景的测试呢?
  • 记录下来系统中每一个重要对象从生到死的过程,即它的生命周期(Lifecycle)。
  • 列出可能的用户,分析他们的兴趣点和目的。
  • 列出潜在系统破坏者类别,从他们为什么要破坏本系统的出发点来分析(例如,为了好玩、为了出风头、为了盗取钱财)。
  • 列出系统事件,以及特别的系统事件
  • 观察用户行为。
  • 分析同类系统和竞争对手的系统
  • 试图把本系统放到现实环境中去考虑它的运行行为。

Posted in 其它.


如何让Watir脚本在不同环境下运行 3

(五)使用Watir::Waiter::wait_until进行等待操作

使用过watir对网页进行测试的朋友,一定会遇到这样的问题。当使用sleep或者ie.wait的时候,由于网速太慢页面没有在制定的时间内页面没有下载完或者指定等待的时间太短,都会导致脚本不能找指定的html tag,系统会给出警告性语句,接下来的所有存在于这个单元测试的方法都会执行不了,rb会对剩下的所有方法给出同样的警告性错误,非常的让人头痛。

(1)使用ie.wait进行等待操作。

Ie.wait这个方法不好使用在于,它把确定网页是否加载完全交给了ie自己判断,所以有的时候ie会认为自己已经加载完整个网页,而这时ie其实是判断失误的。

(2)使用sleep方法进行等待操作。

Sleep  n ,n是时间数,就是说你想让你的网页进行等待操作都行,但是有的时候并不能够准确的评估出来网页加载所需要的准确时间,有的时候这个方法也是不那么非常好用的,并且如果你给的时间过长,会造成你的测试效率低。

sleep 1 until ie.text.include? “new results are loaded”

上面的例子使脚本一直处于等待状态,知道页面出现”new results are loaded” 才继续执行

(3)使用wait_until方法进行等待操作。

如果你的页面一直不出现“new results are loaded”怎么办?你要一直等待?还是关闭脚本重新来过?如果下次还是遇到相同问题怎么办??

Watir中的Waiter类的“wait_until”方法 ,这个方法让watir一直等待,直到页面出现了所需要的内容,脚本就继续执行下面的步骤;如果在60秒内,页面没有出现所需要的内容,就给出警告性错误信息。

wait_until {ie.text.include? “new results are loaded”}

给朋友们一个简单的列子:

require ‘watir’
browser = Watir::Browser.start(’http://www.google.com’)
# In this case all I care about is the text field existing, you could
# check title, text, anything you’re expecting before continuing
Watir::Waiter::wait_until { browser.text_field(:name, ‘q’).exists? }
browser.text_field(:name, ‘q’).set(’ruby poignant’)

如果想查看更详细的内容,请链接:

http://wiki.openqa.org/display/WTR/How+to+wait+with+Watir

Posted in 其它.


如何让Watir脚本在不同环境下运行 2

(四)使用watir对来对JavaScript Pop Ups进行处理

一直都是在半知半解的状态下使用autoit来对Javascript pop ups进行处理,虽然可以处理成功,但是还是不太明确为什么要这样做才可以点击到“确定”按钮等。前阵子为了使脚本能够在不干扰本机用户的使用情况下正常运行,搜索资料查找到一个非常有用的方法。

(我想如果你仔细读懂了这  个链接中所给出的内容,你处理弹出对话框的问题应该也没有太多的问题了。http://wiki.openqa.org/display/WTR/JavaScript+Pop+Ups

该方法可以方便的让你的脚本正常运行,并且不影响本机用户的正常运行。并且这个方法不需要依靠autoit来运行脚本,仅仅使用win32ole方法来对弹出的对话框进行出来。

步骤为:

(1)              首先向库文件ie-class.rb添加如下代码,(库文件所在位置C:\ruby\lib\ruby\gems\1.8\gems\watir-1.6.2\lib\watir\ie-class.rb)

#/////////////////////////////////////////////////////////////////////////////
#Name: clickprompt
#Description: Waits for the popup to appear and then clicks the ok or cancel button
#
#Arguments: button: The button to be pressed – “OK” or “CANCEL”
# txt: Text to be passed into the prompt dialog box
# waitTime: the waiting time caluclated as waitingtime/0.2 currently set to 50 seconds
#Returns: This returns the popup text if popup is found or ” if no popup is found
#/////////////////////////////////////////////////////////////////////////////
def clickprompt(but=”OK”,txt =”", waitTime = 10)
tim = 0
poptxt= ”
while tim < waitTime
sleep 0.2
pophwnd = Win32API.new(”user32″, “GetWindow”, ‘Li’, ‘L’).Call(@ie.hwnd.to_i, 6)
# the above returns any popup windows that are present for the specific window
tim += 0.2
tim += waitTime if pophwnd != 0
end
return ” if pophwnd == 0
button = but.upcase
outval = ‘ ‘ * 30
Win32API.new(”user32″, “GetWindowText”, ‘Lpi’, ‘L’).Call(pophwnd,outval,30)
popwndtitle = outval.rstrip.chomp(”00″) # window title stored here
outval = nil
#poptype = 0
#alert and confirm have ie6 – Microsoft Internet Explorer
#ie7 – Windows Internet Explorer
#ie8 – Message from webpage
if popwndtitle.include?(”Microsoft Internet Explorer”) ||
popwndtitle.include?(”Windows Internet Explorer”) ||
popwndtitle.include?(”Message from webpage”)
#confirm and alerts have the above 3 window titles
# poptype =1 means this is a javascript alert tag
#poptype = 1
poptxt = handlepopup1(pophwnd,button)
elsif popwndtitle.include?(”Explorer User Prompt”)
#prompts have the above window title
#poptype = 2
poptxt = handlepopup2(pophwnd,button, txt)
elsif popwndtitle.include?(”Connect to”)
#authentication dialog
#also make sure the username and password text fields are present – if present we got the auth dialog
cntrlhwnd = 0
cntrlhwnd = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 1002)
#poptype = 3 if cntrlhwnd != 0 #verified the 2 textboxes are present to enter the values
return ” if cntrlhwnd == 0
poptxt = handlepopup3(pophwnd,button, prompt)
end
return poptxt
end

def handlepopup1(pophwnd, button)
# handles the alerts and confirm dialogs
#Yes there is a popupwindow… hence get the controlhandle for the text control – 65535
cntrlhwnd = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 65535)
#now get the text from the popup
outval = ‘ ‘ * 900
Win32API.new(”user32″, “GetWindowText”, ‘Lpi’, ‘L’).Call(cntrlhwnd,outval, 900)
poptext = outval.rstrip.chomp(”00″)
outval = nil

#confirm ok-1 and cancel-2, alert ok-2
cntrlhwndOK = 0
cntrlhwndCANCEL = 0
cntrlhwndOK = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 1)
if cntrlhwndOK == 0 # only 1 button alert
cntrlhwndOK = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 2)
clickWin32Button(cntrlhwndOK) # done clicking javascript ok button
return poptext
else # this is a confirm with 2 buttons
cntrlhwndCANCEL = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 2)
end
button.include?(”OK”) ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL)
#clickWin32Button(cntrlhwndCANCEL)
return poptext
end
private :handlepopup1

def handlepopup2(pophwnd, button, prompt)
#handles prompt boxes which takes a value as input
cntrlhwndOK = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 1)
cntrlhwndCANCEL = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 2)

# get handle to the text control from the prompt box
cntrlpromptText = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 8132)
#now get the text from the popup
outval = ‘ ‘ * 200
Win32API.new(”user32″, “GetWindowText”, ‘Lpi’, ‘L’).Call(cntrlpromptText,outval, 200)
poptext = outval.rstrip.chomp(”00″)
outval = nil

cntrltextarea = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 8133)
if prompt.size != 0
sendmessage = Win32API.new(”user32″, “SendMessage”, ‘LLpp’, ‘L’)
sendmessage.Call(cntrltextarea, 0×000C, ”, prompt) # calling sendmessage with WM_SETTEXT
end
button.include?(”OK”) ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL)
return poptext
end
private :handlepopup2

def handlepopup3(pophwnd, button, prompt)
# handles the auth dialog box , 3 tries then the 401 page is shown
cntrlhwnd = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 1002)
cntrlusername = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(cntrlhwnd, 1003)
cntrlpassword = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(cntrlhwnd, 1005)
if prompt.size == 2
sendmessage = Win32API.new(”user32″, “SendMessage”, ‘LLpp’, ‘L’)
sendmessage.Call(cntrlusername, 0×000C, ”, prompt[0]) # calling sendmessage with WM_SETTEXT
sendmessage.Call(cntrlpassword, 0×000C, ”, prompt[1]) # calling sendmessage with WM_SETTEXT
end
cntrlhwndOK = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 1)
cntrlhwndCANCEL = Win32API.new(”user32″, “GetDlgItem”, ‘Li’, ‘L’).Call(pophwnd, 2)
button.include?(”OK”) ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL)

end
private :handlepopup3

def clickWin32Button(cntrlhwnd)
Win32API.new(”user32″, “SendMessage”,’LLLL’,'L’).Call(cntrlhwnd, 0×0006, 1,0)
Win32API.new(”user32″, “SendMessage”,’LLLL’,'L’).Call(cntrlhwnd, 0×00F5, 0,0)
end
private :clickWin32Button
(2)对于系统语言的不同,浏览器弹出来的对话框及对话框中的一些按钮也是不尽相同的,所以可能需要像你修改下刚刚所添加进来的clickprompt方法。

比如在中文vista操作系统下的ie7浏览器,弹出来的对话框的title值为中文,所以需要修改下 clickprompt方法下的if语句

if popwndtitle.include?(”Microsoft Internet Explorer”) ||
popwndtitle.include?(”Windows Internet Explorer”) ||
popwndtitle.include?(”Message from webpage”) ||popupwndtitle.include?(”来自网页的消息”)

Posted in 其它.


如何让Watir脚本在不同环境下运行 1

Watir自动化测试

最近一直在忙着修改我的watir自动化脚本,为了让脚本可以在不同的浏览器上及不同的操作系统上都能够正常的运行,真是费尽脑汁去查找相关的资料。嘿嘿,在经理的帮助下,我的脚本终于可以在不同的系统不同的浏览器上运行了。

(一)watir对中文网页的支持

Watir现在的版本已经升级到1.6.5,但是这个版本对中文网页的支持却不如1.6.2,所以当测试中文网页的时候,你需要修改下类库中的win32ole.rb文件,具体路径为:ruby\lib\ruby\gems\1.8\gems\watir-1.6.5\lib\watir,将win32ole.rb文件中的WIN32OLE.codepage = WIN32OLE::CP_UTF8更改为:WIN32OLE.codepage =  WIN32OLE::CP_ACP。

codepage值有下面这些,不行的话可以逐个修改下

WIN32OLE::CP_ACP

WIN32OLE::CP_OEMCP

WIN32OLE::CP_MACCP

WIN32OLE::CP_THREAD_ACP

WIN32OLE::CP_SYMBOL

WIN32OLE::CP_UTF7

WIN32OLE::CP_UTF8

(二)相对工作路径

使用excel文件对watir自动化脚本进行数据驱动。为了方便脚本的管理,在读取excel文件的时候,应该需要使用相对路径。

获得当前执行文件的文件名:_FILE_

获得当前文件的目录:File.dirname(_FILE_)

获得当前执行文件的目录完整路径:

Require ‘pathname’

Pathname.new(File.dirname(_FILE_)).realpath

获得当前执行文件的完整路径:

Require ‘pathname’

Pathname.new(_FILE_).realpath

File.basename(filename[, suffix]):

返回filename中的最后一条斜线后面的部分。若给出了参数suffix且它和filename的尾部一致时,该方法会将其删除并返回结果。

File.basename(filename[, suffix]):

返回filename中的最后一条斜线后面的部分。若给出了参数suffix且它和filename的尾部一致时,该方法会将其删除并返回结果。

File.dirname(filename) :

以字符串的形式返回filename中最后一条斜线之前的部分。若文件名中不含斜线,则返回”.”(当前目录)。

File.expand_path(path[, default_dir]):

path展开为绝对路径后返回该路径字符串。若path是相对路径则以default_dir为基准进行扩展。若没有default_dir或其值为nil时将使用当前目录。

因此当需要获得excel文件要:

File.dirname(File.expand_path(”_FILE_”))+”/****.xls

但是如果你所需要的excel文件在根目录下就可以这样写:

File.dirname(File.expand_path(”_FILE_”))+”*****.xls

(三)获取操作系统的语言

有的时候自动化测试需要根据操作系统语言,来决定脚本应该怎样运行。比如对于中文系统的浏览器,popoup box给出的button会是中文的“确定“,但是在英文系统下的浏览器,popoup box给出的button会是中文的“ok“或者”cancel”.

globalAlloc= Win32API.new(’kernel32′, ‘GetSystemDefaultUILanguage’,”, ‘I’)

puts globalAlloc.Call()

Posted in 其它.


安全测试(三)——安全测试工具paros proxy

        先给出两篇文章,都是介绍和比较现在常用的一些安全测试工具的:
        中文:http://networking.ctocio.com.cn/tips/463/7703463.shtml
        英文:http://sectools.org/web-scanners.html

        从中挑选一个,我选的是Paros Proxy。这是一个对Web应用程序的漏洞进行评估的代理程序,即一个基于Java的web代理程序,可以评估Web应用程序的漏洞。它支持动态地编辑/查看HTTP/HTTPS,从而改变cookies和表单字段等项目。它包括一个Web通信记录程序,Web圈套程序(spider),hash 计算器,还有一个可以测试常见的Web应用程序攻击(如SQL注入式攻击和跨站脚本攻击)的扫描器。

        Paros Proxy的安装和运行需要预先配置JRE环境变量,安装JRE 1.4或以上版本,在PATH环境变量中输入JRE的安装路径,在CLASSPATH环境变量中输入LIB路径。然后就可以安装Paros Proxy了。

    Paros Proxy下载地址:http://sourceforge.net/projects/paros/,windows下照提示安装。然后进行配置。
    首先,paros需要两个端口:8080和8443,其中8080是代理连接端口,8443是SSL端口,所以必须保证这两个端口并未其它程序所占用。(查看端口命令:开始—运行—cmd—netstat,查看目前使用的端口)
    然后配置浏览器属性:打开浏览器(如IE),工具-选项-连接-LAN设置-选中proxy server,proxyname为:localhost,port为:8080。(很显然这之后就不能通过浏览器直接上网了)
    如果你的计算机运行于防火墙之下,只能通过公司的代理服务器访问网络,你还需要修改PAROS的代理设置,具体的方法是:打开paros-工具-Options-connection,修改”ProxyName” and “ProxyPort”两项为代理服务器的名称和端口。

    现在可以运行paros进行测试。
    打开paros之后用浏览器就能上网了,运行你要测试的web应用,paros就会自动抓取其中位于第一层的URL(比如首页的URL),并显示在左侧的“site”栏中。选中一个URL,右键—spider,就能抓取所选层次下一层的所有URL。这样可以把待测应用的所有URL都抓取出来。
    不过paros并不能识别一些特定的URL路径,比如一些URL链接需要在合法登录后才能被识别出来,因此在进行URL抓取时,一定先要登录网站。对于未能被识别出来的那些URL,可以手动添加。打开paros—工具—manual request editor,输入未被抓取的URLS,然后单击SEND按钮,完成手动加入URL,添加成功后的URL将显示在左侧的“site”栏中。
    所有URL被抓取出来之后就可以逐一进行扫描了。可以对单一URL进行扫描,也可以对所有URLS进行扫描。扫描的结果会被保存到本地固定目录。
    例如:

Paros Scanning Report

Report generated at Mon, 14 Dec 2009 11:19:21.

Summary of Alerts

Risk Level Number of Alerts
High 0
Medium 2
Low 0
Informational 0

 

 

Alert Detail

 

Medium (Warning) Password Autocomplete in browser
Description

AUTOCOMPLETE attribute is not disabled in HTML FORM/INPUT element containing password type input. Passwords may be stored in browsers and retrieved.

 

URL

http://******.com/index.php

Other information

<input type=”password” name=”pword” id=”pword”/>
 
Solution

Turn off AUTOCOMPLETE attribute in form or individual input elements containing password by using AUTOCOMPLETE=’OFF’

Reference

http://msdn.microsoft.com/library/default.asp?url=/workshop/author/forms/autocomplete_ovr.asp

 

Medium (Suspicious) Lotus Domino default files
Description

Lotus Domino default files found.

 

URL

http://******.com/?OpenServer
 

URL

http://******.com/?Open
 
Solution

Remove default files.

Reference


    然后就可以对扫描结果进行验证了,比如扫描结果中有一是URL传递的参数中存在SQL注入漏洞,那么将该URL及参数输入到地址栏中,验证结果。

    这个工具并不能对web应用进行全面安全测试,今后还会研究一些其它的工具,结合起来,完善测试。

Posted in 工具, 测试, 自动化.

Tagged with , .


安全测试(二)——手动测试方法

        这里先说一下手动测试的两个出发点,所谓知己知彼,百战不殆,安全测试也要从正反两个方面出发来考虑。一是从己方也就是系统安全本身出发,确保其安全机制正确执行了它们的功能;还有就是从敌方也就是攻击者的角度出发,专门针对模拟攻击者的测试用例。综合这两点,总结了一些方法,由于阅读的资料和相关经验有限,可能不够全面,希望能在将来慢慢补充。

        首先是“输入校验”,输入是攻击者与系统最直接的接触方式,据统计,对于一个web应用,输入校验做的好能阻止90%~95%的攻击。那么应该怎样做好输入校验呢?可以参考以下几个步骤:
        1、找到web应用所有能够接受用户输入的地方,也就是找到所有输入点;
        2、逐个检查每个输入点,确认它们的相应的输入规则和边界。这里最好从合法输入入手,因为你不可能穷举出所有非法输入,但是可以列出所有合法输入;
        3、重点关注隐藏域的输入点,比如cookie和URL参数;
        4、验证来自数据库的信息,这点比较容易被忽视,因为一般都认为来自数据库的信息可信度是很高的,这也是为什么数据库容易成为攻击点;
        5、不光要在客户端进行校验,还要在服务器端进行校验,因为客户端可能会被恶意更改导致危险数据进入系统内部;
        6、注意隐藏异常信息,不要让这些信息成为攻击者的切入点。

        做完输入校验之后,系统相对来说已经比较安全了,然后再对一些常见的安全点进行测试,从网上总结出了如下一些测试点,可以根据需要选择测试:
        1、目录设置:每个目录下应该有index.html或main.html页面,这样就不会显示该目录下的所有内容。选中一幅图片,单击鼠标右键,看是否找到该图片所在的路径。若能找到,在浏览器地址栏中手工输入该路径,看是否发现该站点的信息。
        2、SSL:站点使用SSL进行安全传送。进入一个SSL站点是因为浏览器出现了警告消息,而且在地址栏中的HTTP变成HTTPS。开发部门使用了SSL,测试人员需要确定是否有相应的替代页面。当用户进入或离开安全站点的时候,请确认有相应的提示信息。是否有连接时间限制?超过限制时间后出现什么情况?
        3、登录:验证系统阻止非法的用户名/口令登录,而能够通过有效登录。用户登录是否有次数限制?是否限制从某些IP地址登录?如果允许登录失败的次数为3,你在第三次登录的时候输入正确的用户名和口令,能通过验证吗?口令选择有规则限制吗?  是否可以不登陆而直接浏览某个页面?是否有超时的限制,用户登陆后在一定时间内(例如15分钟)没有点击任何页面,是否需要重新登陆才能正常使用。
        4、日志文件:在后台,要注意验证服务器日志工作正常。日志是否记所有的事务处理?是否有恶意操作失败记录?
        5、非正常访问:主要用于需要验证用户身份以及权限的页面,复制该页面的url地址,关闭该页面以后,查看是否可以直接进入该复制好的地址。
        6、输入框管理:对Grid、Label、Tree view类的输入框未作验证,输入的内容会按照html语法解析出来。
        7、缓冲区溢出:没有加密关键数据,在页面输入密码,页面显示的是 *****,  右键,查看源文件就可以看见刚才输入的密码。
        8、不安全的存储:包括两个方面。帐号列表:系统不应该允许用户浏览到网站所有的帐号,如果必须要一个用户列表,推荐使用某种形式的假名(屏幕名)来指向实际的帐号;浏览器缓存:认证和会话数据不应该作为GET的一部分来发送,应该使用POST。
        9、拒绝服务:攻击者可以从一个主机产生足够多的流量来耗尽狠多应用程序,最终使程序陷入瘫痪。需要做负载均衡来对付。

        最后是针对上篇文章中提到的七种常见攻击设计用例进行测试改良,具体方法可以参见以下资料,这里就不详细列出:
        中文:http://www.51testing.com/?uid-49689-action-viewspace-itemid-74842
        英文:http://www.djangobook.com/en/2.0/chapter20/

        这里再提一下之前性能测试中发生的一些错误,现在看来是并发测试对系统安全的影响。最典型的情况是注册(现在改用邮箱验证之后应该不存在此类问题了)和购物,因为是并发,所以它们的提交和处理时间几乎是一样的,于是在判断是否数据库中已经存在该用户名或者是该用户是否有足够虚拟币的时候,因为是同时判断,所以数据库中的记录就不具有绝对的参考价值了,这也就是为什么在并发时会出现同一用户名多次注册以及购物能购到虚拟币为负。这只是一两个例子,仔细检查应该能发现更多的弱点。

        总的来说,手动安全测试是很耗费时间和精力的,对测试人员的要求也很高,但也是必不可少的。下一篇文章将介绍如何用工具来进行安全测试,以弥补手动测试的不足。

Posted in 测试.

Tagged with , , .


安全测试(一)——安全测试简介

        最近接到关于安全测试的任务,先问了问同在测试行业的一个朋友,安全测试包括系统安全测试和代码安全测试。

        先来简单了解下代码安全,通常可以从如下几个方面来审查代码的安全性:
        代码以缺省值运行吗?
        代码以高优先级运行吗?
        代码是否侦听某个网络接口?
        网络接口是不可靠的吗?
        代码是用C/C++写的吗?
        该代码以前是否有历史弱点?
        该组件是否由安全研究员做过最终详细审查?
        该代码处理敏感或隐私数据吗?
        代码是可复用的吗(例如,某个 DLL、C++ 类头文件、库、或程序集)?
        很显然,代码安全审查需要审查人员具有一定的编程功底,详细信息可以参阅http://www.51testing.com/html/21/1056.html。一般测试人员普遍关注的是系统安全测试。

        系统安全问题中一般包含七个弱点,在这里只把它们一一列出,详细资料可以参阅http://www.djangobook.com/en/2.0/chapter20/(英文)。

  •  SQL Injection:(SQL注入)
      
    SQL注入是最常见的攻击方式,它的主要原理是:攻击者通过改变WEB页的参数(如GET/POST数据或是URLS)直接将SQL片断提交到服务器,并在服务器端执行。
  • Cross-Site Scripting (XSS):(跨站点脚本攻击)
            XSS定义:由于WEB程序没有对用户提交的HTML内容进行适当的转译,这样攻击者就可能在你的WEB页中插入一些HTML语句,这些语句通常以<SCRITP>TAG的形式出现。攻击者通常使用XSS攻击来窃取COOKIES 和SESSION信息,或是欺骗用户将隐私信息暴露给错误对象(又称为钓鱼)。
  • Cross-Site Request Forgery:(跨站点请求伪造)
            CSRF:通过在WEB页或在给用户发邮件中插入恶意代码(通常是链接或是脚本),比如发送一个带有银行取款链接的图片或脚本(通常是HTML或javascript),当用户访问这个图片时,此时页面加载图片过程会隐密地链接到一个远程页面,这个页面会自动向目标站点发起请求,如果这个目标站点仍保留这个用户的COOKIE信息,并且这个COOKIER未过期,那么攻击者就可以在用户不知情的情况以用户的身份登录银行或执行取款操作。CSRF的特性就是利用网站对用户标识的信任,欺骗用户的浏览器发送HTTP请求给目标站点。
  • Session Forging/Hijacking:(Session 伪造/篡改)
            Session 伪造/篡改能通过好几种方法对用户的session信息进行攻击,包括:
            
    man-in-the-middle 攻击:攻击者在各种有线(无线)网之间畅游的时候窥探用户的session资料。
            session 伪造:攻击者用(可能是man-in-the-middle得来的)session资料来伪装成另一用户。
            cookie 伪造:攻击者重写cookie中可能是只读的数据。
            Session 篡改:攻击者诱导用户设置或者重置自己的session ID。
            Session 毒害:攻击者在用户以web形式提交session信息的时候往用户的session资料中注入危险信息。
  • Email Header Injection:(邮件标题注入)
            邮件标题注入和SQL注入的原理类似,通过在EMAIL的SUBJECT中输入一些特殊语句如”\n”,攻击者可以利用这个缺陷通过你的邮件服务器发送垃圾邮件。
  • Directory Traversal:(目录遍历)
            目录遍历是另一种注入类型的攻击,攻击者欺骗文件系统读写服务器不允许操作的文件。
  • Exposed Error Messages:(曝露错误信息)
            开发过程中,如果可以看到错误或历史记录对FIX问题是非常有用的。但是如果这些错误信息被攻击者所获取,那么攻击者就可以通过错误信息而了解到应用程序代码或是数据库或是配置等方面的内容,从而为其攻击提供有力的帮助。
  • Posted in 测试.

    Tagged with , , .


    GameXiu服务器的性能测试情况

            来到ECitySky已经四个月了,大大小小的性能测试做了不少,对服务器也有了一定了解。总结一下各个服务器的性能测试情况吧~

            首先是web server(现在也包括websvc),这是我比较熟悉的领域,用一般常用的性能测试工具录制脚本然后再适当修改设置一下就能测。虽然以前用LoadRunner现在用Visual Studio Team System,不过有点LR的基础用起VSTS来上手还是比较快的,所以web server也是最先测的。其实现在常用的测试工具都比较成熟了,有时觉得哪个好用哪个不好用也是因为对各个工具的熟悉程度不同,尽量精通一种工具,了解其它工具比较好。所以今后多研究研究VSTS测好web server应该不是问题。

            然后是game server,这个比较棘手,因为用一般的性能测试工具录制不了。好在开发那边写了现成的测试脚本,我的任务就只要实现各式各样的并发就行。之前测的时候是用Eclipse写了个小java程序,可是并发数一多(1000左右)就溢出报错,虽说可以弄好几台机器一起跑吧,也不是个好的解决办法。而且所谓的并发其实是用一个for循环写的一个接一个的运行,也就仗着计算机的计算速度快看着就像是同时并发一样。这段时间一直在想怎样解决这个并发数的问题,尝试是否能用LR解决(还是衷情于LR啊~~~),LR好歹支持10000的并发数(虽然也最好分到好几台agent上去吧),算起来也就是10w左右的同时在线了,基本能满足未来一段时间的要求了。有了想法就要实践之,嗯。第一个方法是直接用LR里的java协议写脚本,不过不清楚之前的溢出错误是eclipse的问题还是java本身的问题,脚本还在调试中;第二个方法是直接用LR自带的函数去调用测试脚本,这样就肯定不会存在溢出的问题了,目前也还在摸索中。嗯,总之未来的game server在有测试脚本支持的话还是有办法搞定的。

            再然后就是jabber server,测这个也费了好大劲的。选了一个专门用来测jabber的工具Tsung,别说用了,安装就巨复杂无比,尤其对我这样没怎么接触过Linux系统的来说。脚本还不能录,只能自己写。在网上搜了一堆例子才大概明白怎么写脚本,现在脚本貌似还丢了,唉,只能重新弄。不过好在做过一遍的事再做起来应该能简单不少。于是要测jabber server,首要任务是在windows系统下做一个Linux虚机,这个网上一堆教程了,按部就班应该没什么问题。然后就是装Tsung,写脚本运行咯。当然多多学习Linux是必须的。

            最后是database,据说要聘专人来测我也就没太多研究。最近了解安全性测试的时候,有很多关于SQL注入的文章页提到了相关database测试的问题,相信要有心的话研究一段时间也能测,只是需要的时间和测的质量问题了。

            然而说到底,性能测试其实就像是体检,医生给人体检,定是健康检查、找出病因、开处方,而性能测试人员,就是要性能测试、故障诊断、性能调优,缺一不可。没有人会为了知道自己生病了没而跑去看医生,看医生的目的是为了找出病因和拿到处方,这样才能病愈。性能测试也一样,关键在于故障诊断和性能调优,而我现在欠缺的恰恰就是这些,只会测试的tester不是一个好的tester。我可以说我年轻还没有什么经验,没有经验可以是借口,但没有经验不能永远拿来当借口。要在一天天的工作中成长,将测试进行到底!

    Posted in 测试.