zoukankan      html  css  js  c++  java
  • 记录: 一次解决整型溢出攻击(使用scala,隐式转换)

    最近项目遇到一次整型溢出攻击

    有一个功能,玩家购买num个物品. 每个物品花费14货币. 客户端限制玩家只能购买 1-9999个该物品.

    但是某玩家通过技术手段,获得了客户端的运行权限. 于是发送协议购买该物品 306783379 个

    于是服务器收到请求进行以下处理

    val num = message.getInt("num") //获得客户端发送来的 306783379 

    val cost = num * produc.price  //这里没有校验物品的数量就直接计算总价了. 所以总价是 306783379  * 14

    调用扣除货币数量 cost

    调用发放物品数量 num

    这一眼看起来没什么问题, 但是扣除时发现只扣除了他 10货币. 猛然发现 num是int型的,所以 int  306783379   乘以14后溢出了, 结果是10

    再查发现代码里非常多地方有这种直接是 num * price的, 于是想以最小的改动来封禁这个bug.

    最开始的想法是写一个函数, 参数是相乘的2个数, 如果越界就抛异常. a * b 改为  Util.safeMultiple(a, b) 但发现这么改代码看起来有点蛋疼. 后来决定使用隐式转换

    定义个IntChecker ,和implicit 类SafeInt, 

    package thomaswong025.example1
    
    /**
     * Created by Administrator on 2018/1/9/009.
     */
    object IntChecker {
      implicit class SafeInt(val a: Int){
        def `safe*`(b: Int) = {
          val r = BigDecimal(a) * b
          if (r.isValidInt) r.toInt else throw new RuntimeException(s" $a * $b out of int range")
        }
      }
    }

     做个测试:

    package thomaswong025.example1
    
    import thomaswong025.example1.IntChecker._
    
    object Test {
      def main(args: Array[String]) {
        val a = 306783379
        val b = 14
    
        println(a * b) //输出10
        println(a `safe*` b) //抛异常
      }
    }
    找到其他需要使用安全乘法的地方 把乘号改成 `safe*`, 记得在顶部import 包路径.IntChecker._即可
    如果需要安全加减等操作,也可以直接自己在SafeInt类里加上

    注意: 改成 `safe*` 后, 函数优先级比原来的 * 降低了, 跟其他函数调用的优先级一样. 所以 如果代码里有 a * b / c 变成 a `safe*` b / c 之后, 一定要记得加括号 (a `safe*` b) / c


  • 相关阅读:
    hdu 1823 Luck and Love 二维线段树
    UVA 12299 RMQ with Shifts 线段树
    HDU 4578 Transformation 线段树
    FZU 2105 Digits Count 线段树
    UVA 1513 Movie collection 树状数组
    UVA 1292 Strategic game 树形DP
    【ACM】hdu_zs2_1003_Problem C_201308031012
    qsort快速排序
    【ACM】nyoj_7_街区最短路径问题_201308051737
    【ACM】nyoj_540_奇怪的排序_201308050951
  • 原文地址:https://www.cnblogs.com/drwong/p/8283622.html
Copyright © 2011-2022 走看看