• 记录: 一次解决整型溢出攻击(使用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


  • 相关阅读:
    Docker 中国官方镜像加速
    mysql主从同步
    hadoop相关
    Mac上Ultra Edit的激活
    ansible安装应用软件
    Docker学习第二天-容器
    wwnjld团队第二轮迭代成员分数
    第二轮迭代发布报告
    wwnjld第二轮迭代测试报告
    12.24会议记录
  • 原文地址:https://www.cnblogs.com/drwong/p/8283622.html
Copyright © 2020-2023  润新知