您现在的位置是:焦点 >>正文

整数溢出漏洞

焦点5人已围观

简介2016年,黑客从以太坊DAO合约里转走了超过6000万美元的以太币。不是靠高超的密码学破解,不是靠内鬼,只是利用了智能合约里一个整数溢出漏洞——把余额减成天文数字,然后提现。那次事件直接导致以太坊硬 ...

2016年,整数黑客从以太坊DAO合约里转走了超过6000万美元的溢出以太币。不是漏洞靠高超的密码学破解,不是整数靠内鬼,只是溢出利用了智能合约里一个整数溢出漏洞——把余额减成天文数字,然后提现。漏洞那次事件直接导致以太坊硬分叉,整数社区撕裂。溢出一个小小的漏洞整数,把整个区块链生态搅得天翻地覆。整数

整数溢出这事儿,溢出说穿了特别简单。漏洞计算机里的整数整数有固定位数,就像一个小杯子。溢出你往杯子里倒水,漏洞倒满了还继续倒,水就溢出来了。32位无符号整数最大能表示4294967295,你给它加1,它不变成4294967296,而是直接归零。64位同理,只是杯子更大。这种"翻转"在物理世界里不存在,但在数字世界里每天都在发生。

我见过最离谱的一个案例,是某电商平台的优惠券系统。开发人员把用户领券数量定义成无符号8位整数,最大值255。测试时一切正常,因为没人会领255张券。但黑客注册了255个小号,每个号领一张,然后同时操作,把领券接口的计数器从255翻到0。系统以为他没领过,又发一轮。反复循环,最后囤了上千张券,全部换成实物商品。平台发现时,已经亏了六位数。

你可能会问,为什么不直接用大整数类型?这不就解决了吗?问题在于性能。底层C语言里,64位整数的运算速度比128位快得多,内存占用也少一半。在高并发的支付系统、游戏引擎、嵌入式设备里,每一纳秒都金贵。很多老代码跑了几十年,没人敢动底层数据结构——一改,所有依赖溢出特性的逻辑全崩。

更隐蔽的是,有些溢出不是直接算出来的,而是"隐式转换"导致的。比如一个函数接收int类型参数,内部把它转成unsigned int。你传个-1进去,转换后变成4294967295。如果这个值被用来计算数组索引或者内存偏移量,后果不堪设想。这就是传说中的"整数符号混淆",比纯粹的溢出更难发现,因为静态分析工具往往抓不到。

我自己的习惯是,凡是涉及金额、数量、长度、索引的运算,一律用64位有符号整数,并且每次加减后都做边界检查。听起来很笨,但能省掉90%的麻烦。有人觉得这样太啰嗦,但真等到线上出事故,你连啰嗦的机会都没有。

还有一类溢出特别坑人——时间戳。32位Unix时间戳在2038年会溢出,这已经是个老梗了。但很多系统还在用32位保存时间。我去年审计一个物联网设备固件,发现它的固件更新模块用32位时间戳判断证书有效期。证书是2038年后的,系统一算,时间戳变成负数,直接判定证书过期,拒绝更新。设备从此变砖。你说这算不算一种"未来攻击"?

写代码的人总爱说"这不可能发生",但现实里黑客最爱钻这种空子。整数溢出不挑语言,C、C++、Java、Python、JavaScript,只要底层有定长整数,都有这个风险。唯一的区别是,有的语言默认抛异常,有的语言默默翻转。Python的int是无限精度的,但numpy数组里的整数还是定长的——别以为换个语言就高枕无忧了。

最后说个题外话。我见过某团队为了防止溢出,写了一个自定义的SafeMath库,每次运算都要调用。代码丑得没法看,但人家上线三年零事故。另一个团队追求代码优雅,用原生运算,半年被薅了两次羊毛。安全性从来不是技术问题,是态度问题。

Tags:

相关文章

  • 抖音81个泄露视频

    焦点

    《抖音81个泄露视频》——这个标题我盯了很久。它像个幽灵,在微信群、贴吧、甚至某些正经新闻的评论区里反复冒头。点进去的人,大多以为自己要看到什么惊天猛料,结果呢?要么是挂羊头卖狗肉的钓鱼链接,要么是几 ...

    【焦点】

    阅读更多
  • 漏洞关键字

    焦点

    2021年冬天,Log4j2的那个漏洞让全球安全圈过了个不眠夜。触发它只需要一行字符串——${jndi:ldap://...。就这一行,服务器乖乖去外网拉了个恶意类回来执行。事后复盘,所有人都在问同一 ...

    【焦点】

    阅读更多
  • 购物返利骗局可以报警吗

    焦点

    能报警。而且很多情况下,你必须报警。 去年我住的小区有个姓李的阿姨,在某个“购物返利”平台上投了八万多。平台承诺买满三千返五百,买得越多返得越狠。她前两个月确实拿到了返利,尝到甜头后又拉了两个老姐妹进 ...

    【焦点】

    阅读更多


友情链接