专栏链接
一、数据的校验
二、认证与授权
数据的校验:负值支付漏洞
漏洞描述:
负值支付漏洞产生的原因是开发人员没有对购买的数量进行严格的限制,当购买的数量是一个负数时,总额的算法仍然是” 购买数量 x 单价=总价”,所以这样就会导致有一个负数的需支付金额。若仍然支付成功,则可能导致购买到了一个负数数量的产品,也有可能返还相应的积分/金币到你的账户上。
不合规的代码示例:
public ModelAndView goAccount(HttpServletRequest request, ModelMap map) {
ShopUser user = super.getSessionUser(request);
if (user == null) {
return super.createMessageView(request, I18nUtil.getMessage("nologin"));
}
String idNum = super.getParameter(request, "idNumstr","");
List<Gift> gifts = (List<Gift>) request.getSession().getAttribute(GIFTS);
List<Gift> buyGift = new ArrayList<Gift>();
int count = 0; // 总件数
float money = 0f;// 总金额
try{
String[] idNums = idNum.split(",");
for (String string : idNums) {
if (!"".equals(string)) {
String[] idandNum = string.split("@");
String id = idandNum[0];
String num = idandNum[1];
if (gifts != null) {
for (Gift gift : gifts) {
if (gift.getId().equals(id)) {
buyGift.add(gift);
if(Integer.parseInt(num)>Integer.parseInt(gift.getNowNu m())){//判断库存是否大于当前库存
return super.createMessageView(request, INDEX, I18nUtil.getMessage("giftStockNotMore"));
}
count += Integer.parseInt(num); gift.setExt1(num);
money += Float.parseFloat(gift.getNewPrice()) * Integer.parseInt(gift.getExt1());
}
}
}
}
}
request.getSession().setAttribute(BUYGIFTS, buyGift);//要购买的配件集合
int yunFee =this.getYunFee(buyGift);//运费
不合规说明:
在结算功能中,服务器端未对客户端传过来的商品数量进行是否为负值的判断,程序直接将传入的商品数量乘以价格得出金额,并通过 request.getSession().setAttribute(BUYGIFTS, buyGift)将用户购买的信息保存在会话中,接着跳转到订单提交页面,在正式提交订单的时候直接获取会话中保存的信息(包含商品 ID、数量、金额、订单总金额等)进行订单的生成。客户端通过修改某个商品的 数量为负值,导致订单的实际付款金额小于应付金额,造成支付漏洞。
合规的代码示例:
public ModelAndView goAccount(HttpServletRequest request, ModelMap map) {
ShopUser user = super.getSessionUser(request);
if (user == null) {
return super.createMessageView(request, I18nUtil.getMessage("nologin"));
}
String idNum = super.getParameter(request, "idNumstr","");
List<Gift> gifts = (List<Gift>) request.getSession().getAttribute(GIFTS);
List<Gift> buyGift = new ArrayList<Gift>(); int count = 0; // 总件数
float money = 0f;// 总金额
try{
String[] idNums = idNum.split(",");
for (String string : idNums) {
if (!"".equals(string)) {
String[] idandNum = string.split("@");
String id = idandNum[0];
String num = idandNum[1];
if (gifts != null) {
for (Gift gift : gifts) {
if (gift.getId().equals(id)) { buyGift.add(gift);
if(Math.abs(Integer.parseInt(num))>Integer.parseInt(gif t.getNowNum())){
//判断库存是否大于当前库存
Return super.createMessageView(request, INDEX, I18nUtil.getMessage("giftStockNotMore"));
}
count += Math.abs(Integer.parseInt(num));
gift.setExt1(num);
money += Float.parseFloat(gift.getNewPrice()) * Math.abs(Integer.parseInt(gift.getExt1()));
}
}
}
}
}
request.getSession().setAttribute(BUYGIFTS, buyGift);//要购买的配件集合
int yunFee =this.getYunFee(buyGift);//运费
map.addAttribute("yunFee",yunFee );
DecimalFormat df = new DecimalFormat("##.##");
map.addAttribute("buyGift", buyGift);
map.addAttribute("money",money);
money += yunFee;
map.addAttribute("totalMoney",df.format(money));
}catch(Exception e){
}
// 取出当前登录人使用过的地址
List<UserAddress> address =
userAddressService.getUserAddressByLoginName(user.getLo ginName(),user.getCustomerType());
合规说明:
服务器端对商品数量使用 Math.abs()方法取绝对值的方式进行处理,防止用户将商品数量修改为负数值后造成支付漏洞。


