交易订单的重复提交虽然通常不会直接影响现金流和商品流,但依然会给网站运营方带来损害,如消耗系统资源、影响正常用户订单生成、制造恶意用户发起纠纷的机会等。倘若订单对象是虚拟商品,也有可能造成实际损失。订单重复提交的检查工作本应该由网站自身实现,而 iFlow 业务安全加固平台则可以为未实现这项功能的网站提供防护。


以某开源购物网站为例,攻击者能够轻松实现订单的重复提交。我们看看如何在不修改网站源代码的前提下,使用 iFlow 通过透明加入一次性令牌来阻止订单的重复提交攻击。

一、不检查订单重复提交的原始网站

原始网站系统没有检查订单的重复提交,攻击者可以简单地重复提交订单。

1.1 正常用户访问

已登录用户在选择购买一件商品后,进入到确认订单页面:

用户点击提交订单按钮后,网站回复订单已生成:

可以在我的订单列表中看到刚才的订单:

订单生成的交互过程反映在 HTTP 协议层面如下:

sequenceDiagram
participant 正常用户
participant 浏览器
participant Web服务器
正常用户->>浏览器: 选择购买商品
浏览器->>Web服务器: 请求:/index.php?s=/member/paymentorder
Web服务器->>浏览器: 返回:确认订单页面
浏览器->>Web服务器: 请求:/js/payment_orders/payment_orders.js
Web服务器->>浏览器: 返回:payment_orders.js
浏览器->>正常用户: 显示:确认订单页面
正常用户->>浏览器: 点击提交订单按钮
浏览器->>Web服务器: js发送AJAX:提交订单信息
Note over Web服务器: 系统生成正常订单
Web服务器->>浏览器: 重定向页面:订单已生成
浏览器->>正常用户: 显示:订单已生成

1.2 攻击者访问

攻击者使用 Burpsuite 工具作为浏览器和 Web 服务器之间的代理。

攻击者象正常用户一样选择商品和确认提交后,能够在 Burpsuite 中的 HTTP history 中找到这个提交订单信息的请求。攻击者右键点击 Send to Repeater 后进入 Repeater 标签页。

攻击者通过多次点击 Send 按钮来重复发出请求报文从而重复产生订单,并可以在我的订单中看到多个重复生成的订单,如下图所示:

HTTP 协议层面交互如下:

sequenceDiagram
participant 攻击者
participant 浏览器
participant 攻击工具
participant Web服务器
攻击者->>浏览器: 选择购买商品
浏览器->>Web服务器: 请求:/index.php?s=/member/paymentorder
Web服务器->>浏览器: 返回:确认订单页面
浏览器->>Web服务器: 请求:/js/payment_orders/payment_orders.js
Web服务器->>浏览器: 返回:payment_orders.js
浏览器->>攻击者: 显示:确认订单页面
攻击者->>浏览器: 点击提交订单按钮
浏览器->>攻击工具: js发送AJAX:提交订单信息
rect rgb(250, 128, 128)
Note over 攻击工具: 记录请求报文
end
攻击工具->>Web服务器: 发送AJAX:提交订单信息
Note over Web服务器: 系统生成正常订单
Web服务器->>浏览器: 重定向页面:订单已生成
浏览器->>攻击者: 显示:订单已生成
Loop 重复
rect rgb(250, 128, 128)
攻击者->>攻击工具: 发送已记录的请求报文
end
攻击工具->>Web服务器: 提交订单信息
rect rgb(250, 128, 128)
Note over Web服务器: 系统生成重复订单
end
Web服务器->>攻击工具: 返回响应报文
攻击工具->>攻击者: 忽略响应报文
end

二、iFlow虚拟补丁后的网站

我们在 Web 服务器前部署 iFlow 业务安全加固平台,它有能力拦截、计算和修改双向 HTTP 报文并具备存储能力,成为 Web 应用的虚拟补丁。在本例中,iFlow 在加载订单支付代码时生成并加入一次性随机令牌,在提交订单时检查这个令牌的存在。

2.1 正常用户访问

用户在访问确认订单页面时,浏览器自动加载处理订单支付的 JS 代码 (payment_orders.js)。iFlow 截获这段代码的响应返回,生成一个随机令牌保存在本地存储中,并修改 JS 代码将随机令牌加入到 AJAX 发送列表中。用户在点击提交订单按钮时,JS 代码发出 AJAX 请求将随机令牌随同订单信息一起发出,iFlow 截获请求,检查参数中的令牌是否与保存的令牌一致,并清除本地存储中保存的令牌。对于一个正常用户来说,它们一定是相同的,于是 iFlow 去掉令牌参数,将仅包含订单信息的请求发往 Web 服务器处理。

正常用户的 HTTP 协议交互过程如下:

sequenceDiagram
participant 正常用户
participant 浏览器
participant iFlow
participant Web服务器
正常用户->>浏览器: 选择购买商品
浏览器->>Web服务器: 请求:/index.php?s=/member/paymentorder
Web服务器->>浏览器: 返回:确认订单页面
浏览器->>Web服务器: 请求:/js/payment_orders/payment_orders.js
Web服务器->>iFlow: 返回:payment_orders.js
Note over iFlow: 生成随机令牌并保存
rect rgb(160, 250, 160)
iFlow->>浏览器: 修改:AJAX发送列表中加入令牌
end
浏览器->>正常用户: 显示:确认订单页面
正常用户->>浏览器: 点击提交订单按钮
浏览器->>iFlow: js发送AJAX:订单信息及令牌
rect rgb(160, 250, 160)
Note over iFlow: 与保存的令牌比对:通过
Note over iFlow: 清除保存的令牌
end
iFlow->>Web服务器: 提交订单信息
Note over Web服务器: 系统生成正常订单
Web服务器->>浏览器: 重定向页面:订单已生成
浏览器->>正常用户: 显示:订单已生成

2.2 攻击者访问

如前所示,攻击者记录下正常操作时的提交订单的请求报文,然后用工具重放这段报文。由于在第一次正常提交后,iFlow 已经清除了本地存储中保存的令牌,因此后续的重复提交被 iFlow 拒绝。

攻击者的 HTTP 协议交互过程如下:

sequenceDiagram
participant 攻击者
participant 浏览器
participant 攻击工具
participant iFlow
participant Web服务器
攻击者->>浏览器: 选择购买商品
浏览器->>Web服务器: 请求:/index.php?s=/member/paymentorder
Web服务器->>浏览器: 返回:确认订单页面
Web服务器->>iFlow: 返回:payment_orders.js
Note over iFlow: 生成随机令牌并保存
rect rgb(160, 250, 160)
iFlow->>浏览器: 修改:AJAX发送列表中加入令牌
end
Web服务器->>浏览器: 返回:payment_orders.js
浏览器->>攻击者: 显示:确认订单页面
攻击者->>浏览器: 点击提交订单按钮
浏览器->>攻击工具: js发送AJAX:订单信息及令牌
rect rgb(250, 128, 128)
Note over 攻击工具: 记录请求报文
end
攻击工具->>iFlow: 发送AJAX:订单信息及令牌
rect rgb(160, 250, 160)
Note over iFlow: 与保存的令牌比对:通过
Note over iFlow: 清除保存的令牌
end
iFlow->>Web服务器: 提交订单信息
Note over Web服务器: 系统生成正常订单
Web服务器->>浏览器: 重定向页面:订单已生成
浏览器->>攻击者: 显示:订单已生成
Loop 重复
rect rgb(250, 128, 128)
攻击者->>攻击工具: 发送已记录的请求报文
end
攻击工具->>iFlow: 提交订单信息+令牌
rect rgb(250, 128, 128)
Note over iFlow: 检查保存的令牌:无
end
iFlow->>攻击工具: 中断连接
end

2.3 代码

iFlow 内置的 W2 语言是一种专门用于实现 Web 应用安全加固的类编程语言。它介于配置和通用语言之间,具备编程的基本要素和针对 HTTP 协议的特有扩展,能为业务系统编写涉及复杂判断和动态修改的逻辑。

考虑到安全产品的使用者通常为非程序员,他们习惯面对配置文件而非一段代码。因此,W2 语言虽包含语言要素,仍以规则文件方式呈现,并采用可以体现层次结构和方便词法校验的 JSON 格式。

用 W2 语言实现上述虚拟补丁的代码如下:

[
{
"if": "REQUEST_FILENAME == '/js/payment_orders/payment_orders.js'",
"then": {
"execution": [
"TX.raw_token = md5(random())",
"SESSION.order_token@300 = TX.raw_token",
"TX.js_part = '\"' .. TX.raw_token .. '\"'",
{
"directive": "alterResponseBody",
"op": "string",
"target": "'leavemessage' : leavemessage,",
"substitute": "'leavemessage' : leavemessage, 'order_token' : ${TX.js_part},"
}
]
}
},
{
"if": [
"REQUEST_METHOD == 'POST'",
"REQUEST_FILENAME == '/index.php'",
"@ARGS.s == '/order/ordercreate'"
],
"then": {
"if": "SESSION.order_token",
"then": {
"if": "@ARGS.order_token != SESSION.order_token",
"then": {
"verdict": {
"action": "drop",
"log": "${@ARGS.order_token} is not equal to ${SESSION.order_token}!"
}
},
"else": [
"SESSIOIN.order_token = null",
{
"directive": "alterArgPost",
"op": "unset",
"name": "order_token"
}
]
},
"else": {
"verdict": {
"action": "drop",
"log": "${SESSION.order_token} is not exist!"
}
}
}
}
]

示例代码中有两条规则,分别作用如下:

第一条规则

当浏览器请求 payment_orders.js 时,iFlow 拦截响应报文。它首先生成一个随机令牌 raw_token 并将其存放在会话 (SESSION) 存储变量 order_token 中,然后修改处理用户提交订单的 AJAX 操作,将随机令牌加入到 POST 的发送参数列表中。

第二条规则

当用户执行提交订单时,JS 发出一个 AJAX 的 POST 请求,iFlow 拦截此请求。它检查会话 (SESSION) 存储变量 order_token 和参数中的 order_token,如果前者不存在或者两者不相等,即判定为非法请求。否则,将存储变量 order_token 清除,将请求参数 order_token 消除 (以免影响后端应用),然后发给后端 Web 服务器。

注意:上述会话中的 order_token 标志是保存在服务器端的 iFlow 存储中的,在浏览器端是看不到数据更无法进行伪造的。

三、总结

iFlow 使用两条规则在不修改服务器端代码的前提下,透明地实现了随机令牌的一次性发放和使用,避免了简单的重复提交。

当然,如果攻击者完全模拟用户正常操作,重复发起包含前后 2 次会话的攻击行为,则本文中的规则无法阻挡这种重复提交。但显然这种行为需要更复杂的攻击技巧而不只依靠简单地重放实现,何况,使用 iFlow 还能构建出更复杂的防护策略。(张戈 | 天存信息)

WEB安全新玩法 [8] 阻止订单重复提交的更多相关文章

  1. WEB安全新玩法 [1] 业务安全动态加固平台

    近年来,信息安全体系建设趋于完善,以注入攻击.跨站攻击等为代表的传统 Web 应用层攻击很大程度上得到了缓解.但是,Web 应用的业务功能日益丰富.在线交易活动愈加频繁,新的安全问题也随之呈现:基于 ...

  2. WEB安全新玩法 [5] 防范水平越权之查看他人订单信息

    水平越权是指系统中的用户在未经授权的情况下,查看到另一个同级别用户所拥有的资源.水平越权会导致信息泄露,其产生原因是软件业务设计或编码上的缺陷.iFlow 业务安全加固平台可以缓解部分场景下的水平越权 ...

  3. WEB安全新玩法 [3] 防护交易数据篡改

    在任何涉及交易的系统中,客户与商家之间的交易数据具有核心作用,如购买商品的价格.数量.型号和优惠券等.在客户挑选商品的过程中,这些交易数据逐渐形成:待客户提交订单时,交易数据被商家接收,形成双方认可的 ...

  4. WEB安全新玩法 [4] 防护邮箱密码重置漏洞

    大部分具有账号系统的应用都会提供重置用户登录密码的功能,常见方式之一是:用户输入自己的邮箱地址或手机号,应用向这个邮箱或手机号发送验证码,用户将收到的验证码输入应用中即可完成密码重置.这一过程容易因设 ...

  5. WEB安全新玩法 [2] 防范前端验证绕过

    用户登录,几乎是所有 Web 应用所必须的环节.Web 应用通常会加入一些验证手段,以防止攻击者使用机器人自动登录,如要求用户输入图形验证码.拖动滑动条等.但是,如果验证的逻辑仅仅在前端执行,是很容易 ...

  6. WEB安全新玩法 [6] 防范图形验证码重复使用

    在完成关键业务操作时,要求用户输入图形验证码是防范自动化攻击的一种措施.为安全起见,即使针对同一用户,在重新输入信息时也应该更新图形验证码.iFlow 业务安全加固平台可以加强这方面的处理. 某网站系 ...

  7. WEB安全新玩法 [9] 重置密码之验证流程防绕过

    一般来说,业务流程中出现多个操作环节时,是需要顺序完成的.程序设计者往往按照正常用户的操作顺序实现功能,而忽略了攻击者能够绕过中途环节,直接在后续环节上进行非法操作.iFlow 业务安全加固平台能够在 ...

  8. WEB安全新玩法 [10] 防范竞争条件支付漏洞

    服务器端业务逻辑,特别是涉及数据库读写时,存在着关键步骤的时序问题,如果设计或代码编写不当就可能存在竞争条件漏洞.攻击者可以利用多线程并发技术,在数据库的余额字段更新之前,同时发起多次兑换积分或购买商 ...

  9. Odoo 库存管理-库存移动(Stock Move)新玩法

    库存移动(Stock Move)新玩法 Odoo的库存移动不仅仅是存货在两个“存货地点”之间的移动的基本概念了,他们可以被“串联”在一起,可以用来生成或改变其对应的拣货单 (Picking).链式库存 ...

随机推荐

  1. SpringBoot基础系列之自定义配置源使用姿势实例演示

    [SpringBoot基础系列]自定义配置源的使用姿势介绍 前面一篇博文介绍了一个@Value的一些知识点,其中提了一个点,@Value对应的配置,除了是配置文件中之外,可以从其他的数据源中获取么,如 ...

  2. 关于Linux服务器部署

    服务器信息: 此小节的内容: SecurityCRT:用来连接到Linux服务器命令操作. FTP(FTPRush):本地文件和Linux服务器文件交互的 工具服务器 借助客户端工具来链接到Linux ...

  3. DOS命令行(6)——Windows网络状态及用户管理

    ipconfig --查看计算机中适配器的TCP/IP配置信息 命令格式: ipconfig [/allcompartments] [/? | /all | /renew [adapter] | /r ...

  4. 文氏电桥振荡电路原理详解及Multisim实例仿真

    文氏电桥振荡电路(Wien bridge oscillator circuit),简称"文氏电桥",是一种适于产生正弦波信号的振荡电路之一,此电路振荡稳定且输出波形良好,在较宽的频 ...

  5. 20204107 孙嘉临《Python程序设计》实验一报告

    课程:<python程序设计> 班级:2041 姓名:孙嘉临 学号:20204107 实验教师:王志强 实验日期:2021年4月12日 必修/选修:公选课 ##一.实验内容 1.熟悉Pyt ...

  6. (先导)Git Api对接:获取private_token的两种方式

    " Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.在公司一般用于代码管理:开发用例管理平台时我们选择使用git来管理用例,期间使用了很多git ap ...

  7. 六、JavaSE语言基础之数组

    一维数组(关键字[]) 关于数组的一些概念: 数组是多个基本数据有机组合形成一个复杂数据,是一个引用数据类型数据. 数组:装指定数量元素类型相同的数据的容器. 元素:在数组中,数组中的每个数据称之为数 ...

  8. ABP Framework:移除 EF Core Migrations 项目,统一数据上下文

    原文:Unifying DbContexts for EF Core / Removing the EF Core Migrations Project 目录 导读:软件开发的一切都需要平衡 动机 警 ...

  9. macos 安装telnet命令

    在10.12及以下版本,都内置了telnet命令,但是在10.13中,已经取消了 接下来给大家介绍下如何安装telnet命令 打开"终端",输入: /usr/bin/ruby -e ...

  10. 大数据-Hadoop虚拟机的准备以及配置(三台机子)

    虚拟机的准备 修改静态IP(克隆的虚拟机) vim /etc/udev/rules.d/70-persistent-net.rules 配置网络: Vim /etc/sysconfig/network ...