整数溢出漏洞详解:网络安全小白从零入门

文章目录

    • [1. 什么是整数溢出?](#1. 什么是整数溢出?)
    • [2. 整数溢出的原理(二进制视角)](#2. 整数溢出的原理(二进制视角))
    • [3. 常见整数类型位宽一览](#3. 常见整数类型位宽一览)
    • [4. 整数溢出在网络安全中的危害](#4. 整数溢出在网络安全中的危害)
    • [5. 真实世界案例](#5. 真实世界案例)
    • [6. CTF例题:菜狗杯 - 茶歇区](#6. CTF例题:菜狗杯 - 茶歇区)
      • [攻击 Payload](#攻击 Payload)
    • [7. 如何防范整数溢出?(开发者必备 checklist)](#7. 如何防范整数溢出?(开发者必备 checklist))
    • [8. 总结与学习建议](#8. 总结与学习建议)

1. 什么是整数溢出?

整数溢出(Integer Overflow) 是指:计算机用固定长度的二进制位(bit)来存储整数,当运算结果超出这个"容器"的容量时,就会发生"溢出"------数值被截断或回绕,导致程序行为异常。

比喻

想象一个只能显示两位数字的汽车里程表(00~99):

  • 当前是 99 公里
  • 开了 1 公里后 → 本该是 100,但表只能存两位数字 → 直接回绕成 00

计算机的整数类型(int、long、uint 等)就像这个里程表,每种类型都有固定的"位宽"(bit width),超过上限就会"洒出来"。


2. 整数溢出的原理(二进制视角)

计算机内存中,整数是用二进制补码存储的。

示例:8位无符号整数(uint8,范围 0~255)

  • 255 的二进制:11111111
  • 执行 255 + 1
    • 计算结果:1 00000000(9位)
    • 8位容器只能存低8位 → 00000000(即 0)

代码演示(Python 模拟 8 位溢出)

python 复制代码
def uint8_add(a: int, b: int) -> int:
    return (a + b) & 0xFF  # 保留低8位,模拟溢出

print(uint8_add(255, 1))   # 输出: 0
print(uint8_add(200, 100)) # 输出: 44 (300 - 256 = 44)

有符号整数(补码表示)

有符号整数最高位是符号位(0=正,1=负)。
32位有符号 int(int32) 范围:

  • 最小值:-21474836480x80000000
  • 最大值:21474836470x7FFFFFFF

溢出示例

c 复制代码
// C语言示例(编译运行可验证)
#include <stdio.h>
#include <limits.h>

int main() {
    int max = INT_MAX;           // 2147483647
    printf("MAX: %d\n", max);
    printf("MAX + 1: %d\n", max + 1);  // 输出: -2147483648(溢出回绕到最小负数)
    return 0;
}

3. 常见整数类型位宽一览

位宽 类型 最小值 最大值
8位 uint8 0 255
8位 int8 -128 127
16位 uint16 0 65,535
16位 int16 -32,768 32,767
32位 uint32 0 4,294,967,295
32位 int32 -2,147,483,648 2,147,483,647
64位 uint64 0 18,446,744,073,709,551,615
64位 int64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807

PHP 中 :64位系统下 int 默认就是 int64 ,可通过 PHP_INT_MAX 常量获取最大值。

php 复制代码
<?php
echo PHP_INT_MAX;        // 输出: 9223372036854775807
var_dump(PHP_INT_MAX + 1); // 输出: float(9.223372036854776E+18)
// PHP 7+ 会自动转为 float,但乘法运算中仍可能产生回绕
?>

4. 整数溢出在网络安全中的危害

溢出本身不会让程序崩溃,但它会让逻辑判断失效,成为攻击者的切入点:

  1. 绕过大小/数量限制

    文件上传检查 if ($size > 2*1024*1024),若 $size 接近 PHP_INT_MAX,乘以系数后溢出 → 检查失效。

  2. 缓冲区溢出(Buffer Overflow)

    计算内存分配大小时溢出,导致实际分配内存远小于预期,后续写入数据覆盖其他内存 → 可执行任意代码(RCE)。

  3. 数组索引越界

    用溢出后的负数作为数组下标,读取敏感内存。

  4. 逻辑绕过(权限、价格、计数器)

    游戏货币、区块链转账、电商折扣计算等都可能被刷。

经典代码漏洞示例(文件大小检查绕过)

php 复制代码
<?php
$max_size = 2 * 1024 * 1024; // 2MB
$file_size = $_FILES['file']['size']; // 用户可控

// 危险!未做溢出检查
if ($file_size > $max_size) {
    die("文件太大!");
}

move_uploaded_file(...); // 实际可上传超大恶意文件
?>

改进版(推荐)

php 复制代码
<?php
$file_size = (float) $_FILES['file']['size']; // 转为 float 避免溢出

if ($file_size > 2 * 1024 * 1024 || $file_size < 0) {
    die("文件大小非法!");
}

// 乘法前显式检查
if ($file_size > PHP_INT_MAX / 10) {  // 防止后续乘法溢出
    trigger_error("潜在整数溢出!", E_USER_WARNING);
    die("操作拒绝");
}
?>

5. 真实世界案例

  • OpenSSH 整数溢出(2000s)size * 1024 溢出导致分配 0 字节缓冲区 → 远程代码执行。
  • Ariane 5 火箭爆炸:64位浮点数转16位整数时溢出,火箭自毁(损失5亿美元)。
  • 区块链智能合约 :许多 Solidity 合约因 uint256 溢出被刷币(后引入 SafeMath 库)。
  • 游戏外挂:数量/金钱计算溢出,实现无限刷资源。

6. CTF例题:菜狗杯 - 茶歇区

这道题完美体现了"整数溢出绕过限制":

  • 题目背景:你有 1024 FP(资金),每种食物得分 = 消耗 FP(比率 1:1)。目标得分 > 114514 才能出 flag。
  • 正常情况下:最多得 1024 分 → 不可能。
  • 漏洞点 :后台用 int64 计算 FP = FP - count * costscore = count * score

攻击 Payload

第一次提交(触发 FP 溢出):

  • 咖啡(e)填:932337203685477581(18位,刚好让 count * cost 溢出)
  • 其他食物填 0

第二次提交

  • 再次填相同数字(或 1000000000000000000)
  • 提交后 FP 变成极大正数,得分轻松超过 114514,flag 弹出。

Python 模拟器(本地复现)

python 复制代码
PHP_INT_MAX = 9223372036854775807
FP = 1024
count = 932337203685477581
cost = 1

# 第一次购买(模拟溢出)
new_fp = FP - (count * cost)          # PHP 中可能回绕成负数或极大值
print("第一次后 FP:", new_fp)          # 通常为极大正数

# 第二次购买
score = count * 10                    # 咖啡得分10
print("最终得分:", score)             # 远超114514

Burp Suite 抓包技巧

  1. 正常提交一次,抓到 POST 数据。
  2. 用 Repeater 重复发送两次 payload。
  3. 修改 e=932337203685477581

正常做法(不用BP)参考:ctfshow菜狗杯wp2(新手必刷)(Web部分)


7. 如何防范整数溢出?(开发者必备 checklist)

  1. 输入强制类型转换

    php 复制代码
    $user_input = (float) $_POST['count']; // 优先用 float
  2. 乘法前显式检查

    php 复制代码
    if ($count > 0 && $cost > PHP_INT_MAX / $count) {
        die("数值过大,拒绝操作!");
    }
  3. 使用安全库

    • PHP:gmp 扩展处理任意精度整数。
    • C/C++:SafeInt__int128
    • Python:原生支持无限大整数,无需担心。
  4. 边界检查 + 日志

    所有用户输入必须经过 is_numeric() + 范围检查 + trigger_error

  5. 代码审计 checklist

    • 文件大小(filesize()
    • 数组索引(isset() + count()
    • 内存分配(str_repeat($str, $size)
    • 循环计数器

8. 总结与学习建议

整数溢出本质是:"计算机的整数不是数学上的无限大,而是有容量上限的固定容器,装不下就会洒出来,洒出来的那一刻就是漏洞。"

下一步行动

  1. 本地搭建 PHP 环境,运行上面的所有代码示例。
  2. 去 CTF 平台搜"整数溢出"标签,再刷 2-3 道题。
  3. 阅读 OWASP Top 10 中的"注入"和"安全配置错误"章节。
  4. 推荐书籍:《白帽子讲 Web 安全》、《C 语言安全编程》。

最后思考:安全从来不是"加固",而是"从设计之初就考虑边界"。下次写任何数量、价格、索引相关的代码,都提醒自己问一句:"这个数会不会溢出?"

参考

  • PHP 官方文档:PHP_INT_MAX
  • 文章《PHP的整数溢出漏洞:在处理文件大小或数组索引时的边界检查与位宽问题》
  • 菜狗杯 2025 茶歇区题目
相关推荐
qq_260241232 小时前
将盾CDN:威胁情报驱动的网络安全防御新范式
安全·web安全
黎阳之光3 小时前
黎阳之光:以视频孪生领跑全球,赋能数字孪生水利智能监测新征程
大数据·人工智能·算法·安全·数字孪生
qq_260241234 小时前
将盾CDN:网络安全态势感知的建设与实践
安全·web安全
一袋米扛几楼985 小时前
【网络安全】Splunk 是什么?
安全·web安全
一袋米扛几楼985 小时前
【网络安全】SIEM -Security Information and Event Management 工具是什么?
前端·安全·web安全
AI_Claude_code5 小时前
ZLibrary访问困境方案三:Web代理与轻量级转发服务的搭建与优化
爬虫·python·web安全·搜索引擎·网络安全·web3·httpx
上海云盾-小余5 小时前
DDoS 攻击全解析:常见类型识别与分层防御思路
网络协议·tcp/ip·安全·ddos
www4395 小时前
Vulinbox(敏感信息与敏感文件泄露)
安全
智擎软件测评小祺6 小时前
渗透测试报告关键模块拆解
网络·web安全·渗透测试·测试·检测·cma·cnas