深入探析 Rational AppScan Standard Edition 多步骤操作
序言
IBM Rational AppScan Standard(下文简称 AppScan)作为面向 Web 应用安全黑盒检测的自动化工具,得到业界的广泛认可和应用。很多人使用 AppScan 时都采用其强大的手工探索加自动探测的方式,然而这种方式并不适用于所有场景。使用 AppScan 进行安全扫描时,我们必须保证 AppScan 探索出来的 URL 的有效性(尤其是用户想导出这些探索结果以供复用的情况下),有效性即指该 URL 对应的 HTTP 请求能被服务器端接受并按照期望的方式进行处理。某些场景下若干个 URL 必须以特定的顺序执行时方才有效。在这种场景下,前面提及的探测方式不一定能保证所探测出来的 URL 的有效性,因此可能会导致部分 URL 测试失败。利用 AppScan 的多步骤操作可以处理必须依特定顺序执行的若干 URL 的有效性问题。本文将跟读者分享 AppScan 多步骤操作所适用的场景,剖析 AppScan 多步骤操作的基本原理,并结合案例向读者演示了多步骤操作的使用方法。
多步骤操作的适用场景
多步骤操作主要应用于若干 URL 必须以特定顺序执行的场景。譬如在线购物,用户需要先挑选商品到购物车中,然后提供支付及物流信息,最后才能确认订单生效完成订购。从功能逻辑角度看,这 几个步骤之间存在明确的先后顺序。从编码实现的视角来看,这个过程中前一个页面提交的用户数据会被保存在服务器端譬如会话(session)中,后面的页 面会取用这些数据,如果会话中没有这些数据,系统会抛出异常导致后续 URL 无法访问。通常来说,在线购物、用户注册等向导性的操作页面都存在这样的特性。
利用手工探索的话,AppScan 可以探索出以上场景中的所有 URL。但一旦进入测试阶段,由于 AppScan 测试的时候通常是多线程并发测试,并不能保证以上 URL 测试的先后顺序。如果后面的 URL 对应的测试变体先被执行,服务器端会因为会话中数据不完整抛出异常,导致这个测试变体的 HTTP 响应为 500 错误,这样的话该测试变体原本所计划的模拟攻击根本没机会被执行。因此,这种场景下直接探索加测试的方式可能会漏掉一些安全测试用例。
分 析完以上场景及原理后,识别多步骤操作的适用场景也就不再困难了。笔者推荐两种方法:首先,我们推荐安全测试人员在测试开始前要对被测试 Web 应用进行综合评估(建议将“检查是否存在特定顺序执行的 URL”记录到 Web 应用评估的检查清单中),条件允许的话尽量找机会跟系统开发人员进行沟通交流,毕竟开发人员最明白哪些 URL 必须以特定的顺序执行。除此之外,条件允许的话,我们建议启用 AppScan 测试过程中的请求 / 响应记录(通过“工具 - 选项 - 扫描选项 - 启用请求 / 响应记录”启用日志记录)。测试过程中应注意观察请求 / 响应记录。如果记录中大量连续出现 500 错误响应,则要仔细分析这些发生 500 错误的请求及响应,推荐使用 AppScan 内置工具 HTTP Request Editor 依次执行其上下文的 URL,检查这些 URL 是否必须顺序执行。
多步骤操作的基本原理及使用
下面本文将介绍 AppScan 多步骤操作的基本原理,以帮助读者理解多步骤操作是如何处理多 URL 特定顺序执行的场景。我们通过一个简单的场景来说明多步骤操作的原理。假设用户在线购物包括三个页面:第一页,用户添加商品到购物车中;第二页,用户填写 付款和物流信息;第三页,用户确认订单并提交。当我们使用多步骤操作将以上三个页面当作一个序列来执行。AppScan 会先测试第一页;测试第二页时会先执行第一页;测试第三页时会先依次执行第一页、第二页。值得注意的是,测试第二页时,每个测试变体执行前都会执行第一 页,同理,测试第三页时,执行每个第三页的测试变体前也都会依次执行第一、二页。依次类推。这样即保证了执行每个 URL 的测试变体前,其依赖的前置 URL 都被执行过。但需要注意的是,多步骤操作相比较普通扫描来说,其执行过程中会大量重复执行前置 URL,所以实际使用中应尽量控制序列中步骤数量(即 URL 数量),否则易出现性能问题。通常建议将多步骤操作的序列数量限制在五个,其中每个序列中的步骤数不超过 25 个,总步骤数不超过 70 个。
多 步骤操作使用起来比较直观明了。图 1 展示了多步骤操作的视图。在此视图中,用户可以记录序列(通过点击图中的红色圆点按钮可以录制序列)。录制多步骤操作序列会有两个选项:“登录然后记录” 和“不登录便记录”。前者会自动执行登录序列,然后开始记录序列,但不会将登录记录为序列的一部分;后者会将所有的 URL 都记录下来。我们需要注意的是,序列被播放测试时,AppScan 不进行会话状态监测。因此如果序列播放过程中导致用户从 Web 应用中被注销,AppScan 不会自动执行登录序列。这种情况下,建议用户将登录过程录制到序列中,从而保证每次运行序列时都会回放登录。
图 1. 多步骤操作视图
此外,图 1 中还有几个重要的配置项需要读者细致理解。
- “启用该序列的回放”选项控制了当前序列的启用 / 停用状态。如果该选项被选中,则该序列被启用,测试多步骤操作的时候该序列会被执行;如果没有选中,该序列即被停用,执行多步骤操作的时候该序列将被忽略。
- “允 许播放优化”选项提供了 AppScan 引擎对于当前序列的性能优化处理。如果该选项被选中,AppScan 会根据内置算法判断序列中 URL 中的关系,判断是否可以跳过前面的 URL 直接测试后面的 URL,同时 AppScan 会尝试使用多线程扫描该序列,从而实现了性能的提升。
- “以 单线程方式测试”选项跟选项“允许播放优化”有相关性。如果“允许播放优化”被禁用,AppScan 则自动以单线程方式测试。如果“允许播放优化”被启用,如上文所述 AppScan 会尝试使用多线程扫描。如果用户确定该场景的业务逻辑不应该多线程并发执行的话,建议启用“以单线程方式测试”选项。
序列录制 完成后,通常有两种方式启动多步骤操作的安全测试。如果想仅测试多步骤操作,则点击菜单“扫描 - 仅测试多步骤操作”启动多步骤操作的安全测试,如图 2 所示。如果想执行多步骤操作及其他全部扫描任务,则运行菜单“扫描 – 完全扫描”启动完全扫描,完全扫描时,AppScan 会检查当前是否有多步骤操作序列存在,有的话会自动启动多步骤操作的安全测试。
图 2. 测试多步骤操作
多步骤操作的序列变量表达式
到目前为止,一切看起来都非常直观而简单。下面我们来看 看另外一种典型的多步骤序列场景,用户注册。假设某系统区分个人用户和企业用户,其用户注册页面包含三个页面:第一页需要用户输入用户名、邮箱及申请的用 户类型,第二页要求用户输入对应用户类型的其他信息,第三页是注册信息确认页面。显而易见,这个场景跟前文提及的购物车场景比较相似,后一页面依赖于前一 页面提供的输入信息,这三个页面需要按照顺序执行,否则会出现访问错误。不同点在于,第一个页面中的用户名和邮箱只能输入一次,因为系统设计时会约束用户 名和邮箱的唯一性。
按照前面 AppScan 多步骤操作的原理来看,每次执行第二、三页面的测试时,都会执行第一页,这样的话,同一个用户名和邮箱会被重复使用,这显然会违反唯一性约束,因此 Web 应用会抛出系统异常,导致第二、三页测试无法正常进行。我们立刻会想到,如果 AppScan 每次执行第一页的时候能够自动更新用户名和邮箱,这个问题即可以完美解决。确实如此,AppScan 确实提供了丰富的序列变量表达式,帮助用户解决参数值的自动更新问题。
AppScan 内置序列变量表达式
参照 IBM 官方文档,AppScan 目前提供五种内置表达式来实现序列变量以递增或随机数的方式进行自动更新。下文将跟读者逐个解释各个序列变量表达式的作用。
__SeqVariable__<variable id>__random_integer(min,max)__
该序列变量表达式支持用户定制随机整数作为参数值或者参数值的一部分。<variable id> 为用户指定的参数名称,以便用户识别该参数(注:下 文其他序列变量表达式中的 <variable id> 作用相同,不再赘述)。例如:用户想设计序列变量“username”的参数值以随机方式生成,譬如 user11,user31,user45 等,即可设计序列变量的参数值为“user__SeqVariable__p1__random_integer(10,99)__”。
__SeqVariable__<variable id>__incrementing_integer(min,increment)__
该 序列变量表达式支持用户定制递增整数作为参数值或者参数值的一部分。例如:用户想设计序列变量“username”的参数值以递增的方式自动生成,譬如 user1,user2,user3 等。即可设计序列变量“username”的参数值为 “user__SeqVariable__p2__incrementing_integer(1,1)__”。
__SeqVariable__<variable id>__random_string(length)__
该 序列变量表达式支持用户定制指定长度的随机字符串作为参数值或者参数值的一部分。例如:用户想设计序列变量“username”的参数值是五位的随机字符 串。序列变量“username”的参数值即可设计为“__SeqVariable__p3__random_string(5)__”。
__SeqVariable__<variable id>__date_time()__
该 序列变量表达式支持用户定制日期值作为参数值或者参数值的一部分。例如:用户想设计序列变量“email”的参数值是“appscan 日期 @ibm.com”,即可设计其参数值为“appscan__SeqVariable__p4__date_time()__@ibm.com”。
这 里需要注意的是,AppScan 使用的日期时间显示格式为“MMddyyHHmmss”。MM 用两位数字表示当前月(例如,04 代表四月);dd 用两位数字表示本月当前天数(例如,16 代表 16 日);yy 用两位数字表示当前年(例如,12 代表 2012 年);HH 用两位数字表示 24 小时制的小时数(例如,13 代表下午 1 点);mm 用两位数字表示当前分钟;ss 用两位数字表示当前秒数。例如:如果当前时间是 2012 年 4 月 16 日下午 1 点 02 分 03 秒,生成的日期即为“041612130203”。
__SeqVariable__<variable id>__ date_time_milliseconds()__
该序列变量表达式跟上一个表达式类似,只是其精确度准确到毫秒。
序列变量表达式的使用方法
前 文介绍了五种 AppScan 内置序列变量表达式。但图 1 所示多步骤操作视图中并没有提供界面供读者修改序列变量的值。目前我们只能先将序列导出到本地文件 .seq 文件,然后用编辑器如记事本等打开 .seq 序列文件,找到对应的序列变量定义处,手工将其变量值修改为以上序列变量表达式。
譬如,我们想将某注册申请表单中的注册 ID 修改为“test 日期时间 @ibm.com”的参数格式。通过记事本打开导出的序列文件,即可找到对应表单中的 uid 参数,如清单 1 所示。
清单 1. 序列文件中的原始参数
<request SessionRequestType="Login" method="POST" scheme="http" httpVersion="HTTP/1.0" numberOfPatternParameters="0" host="demo.testfire.net" port="80" path="/doRegistration" contentType="URLENCODING" boundary="" pathQuerySeparator="?" japEncoding="14"> <parameter name="uid" value="jsmith@test.com" type="BODY" linkParamType="simplelink" separator="&" operator="=" /> ... </request>
将清单 1 中所示序列变量“uid”的值修改为 “test__SeqVariable__uid__date_time_milliseconds()__@ibm.com”并保存序列文件。接下来在 多步骤操作视图中删掉原来的序列,导入修改后的序列文件。然后运行多步骤操作即可观察到序列变量“uid”的值在运行过程中被动态更新为 “test041412193400359@ibm.com”等参数值。
清单 2. 序列文件中的序列参数表达式
<request SessionRequestType="Login" method="POST" scheme="http" httpVersion="HTTP/1.0" numberOfPatternParameters="0" host="demo.testfire.net" port="80" path="/doRegistration" contentType="URLENCODING" boundary="" pathQuerySeparator="?" japEncoding="14"> <parameter name="uid" value="test__SeqVariable__uid__date_time_milliseconds()__@ibm.com" type="BODY" linkParamType="simplelink" separator="&" operator="=" /> ... </request>
案例:使用 AppScan 多步骤操作
笔者基于 IBM 演示 Web 安全漏洞的 Altoro Mutual 系统,实现了一个简单的多 URL 特定顺序执行的场景。下面本文将跟读者简介这个案例场景,以及如何利用 AppScan 多步骤操作实现该场景的安全扫描。
案例场景介绍
图 3- 图 6 展示了该场景的全过程。用户登录成功 AltoroMutual 银行系统后可以进行转账。该转账包括三个步骤:首先用户需要指定资金转出帐号,然后指定资金转入帐号,最后提供转账金额后进行转账,转账成功后系统会显示 转账成功信息。为方便读者了解笔者所实现的场景,下文将结合截图介绍各个页面的概要实现方式。图 3 中用户提供了资金转出帐号后,点击下一步按钮后,表单将会提交至下一个页面的 JSP 文件。
图 3. 选择资金转出帐号
图 4 中的 JSP 文件会检查请求中是否存在资金转出帐号,没有的话抛出异常,有的话将资金转出帐号暂存在会话中。用户提供资金转入帐号后,点击下一步按钮后,表单将会提交至下一个页面的 JSP 文件。
图 4. 选择资金转入帐号
图 5 中的 JSP 文件会检查请求中是否存在资金转入帐号,没有的话抛出异常,有的话将资金转入帐号暂存在会话中。用户填写转账金额后,点击转账按钮时,表单会提交至下一个页面。
图 5. 转出资金金额
图 6 页面将从会话中获取资金转入帐号和资金转出帐号,从 HTTP 请求中获取转账金额,进行参数检验后即执行转账逻辑。转账执行成功后,展示成功信息。
图 6. 资金转账成功
案例扫描配置
下面本文将跟读者详细介绍该案例的扫描配置过程。
- 新建 Web 应用程序扫描,笔者直接选择 AppScan 预定义的 demo.testfire.net 模板,如图 7 所示。选择扫描类型为 Web 应用程序扫描,然后点击下一步,使用默认起始 URL、登录序列及测试策略;
图 7. 新建扫描
- 在“完成扫描配置向导”界面中选择“我将稍后启动扫描”,然后点击“完成”,如图 8 所示。选择菜单“文件 - 保存”,将当前扫描配置保存。
图 8. 完成扫描配置向导
- 点击菜单“扫描 - 扫描配置”,打开扫描配置对话框,点击左侧“多步骤操作”进入多步骤操作视图。如图 9 所示,选择“登录后记录”进行录制多步骤序列。在 AppScan 打开的浏览器,手工探索上文所介绍案例中的完整转账过程。
图 9. 录制多步骤序列
- 检查 AppScan 所记录的各个步骤及其 URL,见图 10。读者在实际项目过程中一定要注意检查这些 URL,将跟该场景无关的一些 URL 剔除掉,前文已经强调过要尽量控制序列中步骤数量,否则易出现性能问题。点击确定按钮,然后保存当前扫描配置。
图 10. 检查录制好的序列
- 点击菜单“扫描 - 仅测试多步骤操作”启动该序列的安全扫描。点击菜单“查看 - 扫描日志”,即可看到 AppScan 会先执行登录序列,然后加载多步骤操作序列,一一执行验证序列中各个 URL 的有效性,然后针对各个 URL 一一进行测试。
图 11. 扫描日志
至 此,一个简单的多步骤操作的扫描演示即已完成。如果用户在实际工作中遇到前文提及的参数唯一性约束问题时,用户仅需要在图 10 所示的多步骤操作视图中,导出当前序列,然后按照清单 1、2 所示方法修改序列文件,然后导入修改好的序列文件,废除原先的序列文件,重新执行多步骤操作扫描即可。
结论
本文跟读者分享了如何利用 Rational AppScan Standard Edition 处理多个 URL 必须以特定顺序执行场景下的安全扫描。笔者实际工作中发现很多用户忽视了这种场景的特殊性,将之以普通探索测试的方式进行扫描,导致了很多 URL 的漏洞扫描用例没有真正被执行。因此笔者特整理此文介绍 URL 特定顺序执行场景的特殊性,并深入探析 AppScan 所提供的解决方案 —— 多步骤操作 —— 的原理及使用方式。多步骤操作实际应用中往往会遇到参数唯一性约束问题,因此本文还跟读者分享了如何使用序列变量表达式实现参数的定制更新。最后本文结合 案例跟读者演示了 AppScan 多步骤操作的使用方法。希望此文能为读者改进扫描质量有所帮助。
转载自:http://www.ibm.com/developerworks/cn/rational/r-cn-appscanmultiplesteps/