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


原文地址:https://www.cnblogs.com/drwong/p/8283622.html

时间: 2024-12-22 02:42:17

记录: 一次解决整型溢出攻击(使用scala,隐式转换)的相关文章

C语言的整型溢出问题(转)

整型溢出有点老生常谈了,bla, bla, bla… 但似乎没有引起多少人的重视.整型溢出会有可能导致缓冲区溢出,缓冲区溢出会导致各种黑客攻击,比如最近OpenSSL的heartbleed事件,就是一个buffer overread的事件.在这里写下这篇文章,希望大家都了解一下整型溢出,编译器的行为,以及如何防范,以写出更安全的代码. 什么是整型溢出 C语言的整型问题相信大家并不陌生了.对于整型溢出,分为无符号整型溢出和有符号整型溢出. 对于unsigned整型溢出,C的规范是有定义的——“溢出

【C语言】整型溢出和整型提升

什么是整型溢出: C语言的整型问题相信大家并不陌生了.对于整型溢出,分为无符号整型溢出和有符号整型溢出. 对于unsigned整型溢出,C的规范是有定义的--"溢出后的数会以2^(8*sizeof(type))作模运算",也就是说,如果一个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模.例如: unsigned char x = 0xff; printf("%d\n", ++x); 上面的代码会输出:0 (因为0xff + 1是25

C#--整型与字节数组byte[]之间的转换

转:https://www.cnblogs.com/dayang12525/p/6393941.html using System; int  i = 123;byte [] intBuff = BitConverter.GetBytes(i);     // 将 int 转换成字节数组lob.Write(intBuff, 0, 4);i = BitConverter.ToInt32(intBuff, 0);           // 从字节数组转换成 int double x = 123.45

CPython对象模型:整型

前一篇:CPython对象模型:基础 程序中,最常用的数据类型之一就是整型了. 本篇博文记录的就是研究整型过程中的一些心得. 1 PyLongObject 1.1 版本之别 在python2.x中,整型对象还有两种:不太大的整数int(约等于C语言中long)和大整数long. 在python3之后,这两种类型合并为int,但新的int类型的表现和2.x中的long其实更为接近. 在python2.x中,int是一个定长的类型,并且采用了两个不同的内存池分别存放小整数和大整数: 但在python

整型信号量与记录型信号量

信号量机构是一种功能较强的机制,可用来解决互斥与同步的问题,它只能被两个标准的原语wait(S)和signal(S)来访问,也可以记为"P操作"和"V操作". 原语是指完成某种功能且不被分割不被中断执行的操作序列,通常可由硬件来实现完成不被分割执行特性的功能.如前述的"Test-and-Set"和"Swap"指令,就是由硬件实现的原子操作.原语功能的不被中断执行特性在单处理机时可由软件通过屏蔽中断方法实现. 原语之所以不能被中

PDO 查询mysql返回字段整型变为String型解决方法

PDO 查询mysql返回字段整型变为String型解决方法 使用PDO查询mysql数据库时.运行prepare,execute后,返回的字段数据全都变为字符型. 比如id在数据库中是Int的.查询后返回是String型. 对于php这样的弱类型的语言.影响不大. 在做API返回数据时.假设类型与数据库不一致,对于java和Objective C这些强类型,影响就非常大了. 解决方法: <?php $pdo = new PDO($dsn, $user, $pass, $param); // 在

PHP长整型在32位系统中强制转化溢出

CleverCode近期遇到一个PHP项目整形转化问题,mysql有一个字段id是bigint的,里面有长整型,如id = 5147486396.可是php代码因为历史原因却部署在多台机器中,当中A机器32位系统中,B机器64系统中.如今的问题是64系统中页面訪问正常.32位系统中訪问出错了.原因是php整形溢出. 1 A机器演示 1.1 获取A机器系统位数 # getconf LONG_BIT 1.2 整形转化代码 <? php $id = 5147486396; echo '$id:'.$i

unsigned 整型实现无溢出运算

普通的 int 整型能表示的范围很有限,所以刷题时很多时候不得不用 long long 来存更大的数据.或者找出数列中某个只出现一次(或奇数次)的数(其余的数均出现两次 / 偶数次),用异或运算的经典题目,然而,如果数据范围不大的话,O(n) 的复杂度下,把第一次出现的所有数全加 / 乘起来,然后再减 / 除去第二次出现的 n - 1 个数(缺少的那个就是要求的数),原理是可以的,只是一般 OJ 出这样的题目必然不会让你用这种小学生的思维去做,所以会把数据设置得奇大,让你一累加必然溢出,更不用说

基于 CPython 解释器,为你深度解析为什么Python中整型不会溢出

前言 本次分析基于 CPython 解释器,python3.x版本 在python2时代,整型有 int 类型和 long 长整型,长整型不存在溢出问题,即可以存放任意大小的整数.在python3后,统一使用了长整型.这也是吸引科研人员的一部分了,适合大数据运算,不会溢出,也不会有其他语言那样还分短整型,整型,长整型...因此python就降低其他行业的学习门槛了. 那么,不溢出的整型实现上是否可行呢? 不溢出的整型的可行性 尽管在 C 语言中,整型所表示的大小是有范围的,但是 python 代