二进制漏洞利用 | 整数溢出探究

admin 2024年10月16日18:02:22评论32 views字数 9466阅读31分33秒阅读模式

扫码领资料

获网安教程

二进制漏洞利用 | 整数溢出探究

二进制漏洞利用 | 整数溢出探究

Track安全社区投稿~  

千元稿费!还有保底奖励~(https://bbs.zkaq.cn)

什么是整数溢出?

整数溢出是指当算术运算的结果超出用于存储该结果的数据类型的容量时发生的现象。简单来说,就是当一个数值变得过大(对于有符号整数来说,也可能是过小),无法被正常存储,从而导致意外结果。

举个例子,假设有一个有符号的32位整数,其存储范围为 -2,147,483,648 到 2,147,483,647。如果你试图给最大值(2,147,483,647)加上 1,数值会回绕到最小值(-2,147,483,648),这在关键系统中可能引发严重后果。

为什么会发生整数溢出?

存储限制:定长整数(如 intshort 等)有固定的边界。例如:

有符号32位整数的范围是 -2,147,483,648 到 2,147,483,647
如果你试图将 2,147,483,648 存储在32位整数中,就会发生溢出,通常会回绕到负数。
输入验证不充分:如果用户输入未经过正确的验证,并且运算未进行边界检查,就可能发生溢出。
示例
#include <stdio.h>int main() { int a = 2147483647; // Maximum value for a 32-bit signed integer int b = a + 1; // This causes an integer overflow printf("Overflowed Value: %dn", b); return 0;}
输出
Overflowed Value: -2147483648
在这种情况下,将 1 加到最大整数会导致它回绕到最小的负值,这就是典型的溢出现象。
二进制漏洞利用 | 整数溢出探究

整数溢出漏洞的历史回顾

由于编程语言中的数据类型具有固定大小,整数溢出自计算机发展早期起就成为了一个问题。在早期系统中,开发人员常常需要在有限的硬件条件下工作,使用诸如 int 和 short 之类的数据类型来节省内存。因此,特别是在涉及安全的关键软件中,溢出问题时有发生。
20世纪90年代和2000年代,随着软件行业的成熟,研究人员和攻击者逐渐发现,整数溢出可能导致内存损坏、缓冲区溢出,甚至任意代码执行。在这一时期,攻击者利用整数溢出的特点,使系统误计算缓冲区大小,从而引发缓冲区溢出——这是最危险的漏洞之一。
历史上关键的漏洞
1.OpenSSH (2002):OpenSSH中的整数溢出漏洞(CVE-2002-0083)允许攻击者触发缓冲区溢出。
2.Windows Metafile (2005):Windows Metafile文件处理中的整数溢出导致了关键的代码执行漏洞(CVE-2005-4560)。

与整数溢出相关的CVE数量(截至2024年9月)

整数溢出一直是CVE(通用漏洞披露)中的常见问题。这类漏洞在各种软件产品中被利用,包括网络浏览器、操作系统、库和网络服务。
截至2024年9月,根据公共CVE数据库的统计:
大约有 2,500到3,000个CVE 与“整数溢出”相关。这些CVE涵盖了具体的整数溢出问题以及与整数相关的漏洞,如整数下溢整数回绕
值得注意的例子包括:
CVE-2016-1019:Adobe Flash中的一个严重整数溢出漏洞,导致远程代码执行。
CVE-2021-34484:Windows中的整数溢出漏洞,导致本地权限提升。
CVE-2008-0015:OpenSSL中的整数溢出导致内存损坏。

为什么有这么多与整数溢出相关的CVE?

1.普遍性:整数数据类型是许多编程语言的基础。因此,整数运算错误影响范围广泛的各类软件产品。
2.严重性:利用整数溢出可能导致严重的内存错误,使攻击者能够绕过安全检查、提升权限或实现代码执行。
3.代码库的演进:随着代码库的扩展以及遗留系统与现代应用的集成,整数溢出问题的出现机会增多。

什么使应用程序容易遭受整数溢出攻击?

要让一个应用程序容易受到整数溢出的攻击,必须存在某些条件因素。当整数运算(加法、减法、乘法等)产生的结果超出变量的存储容量时,可能会导致错误或恶意后果。

使应用程序易受攻击的因素:

使用固定大小的数据类型
32位或64位整数在C、C++、Java、Python(Python 3之前版本)等编程语言中广泛使用,甚至在某些数据库中也常见。固定大小的数据类型(如 intshort 等)有上下限,如果应用程序没有正确处理大或小的输入值,就可能发生溢出。
例如,带符号的32位整数范围是 -2,147,483,648 到 2,147,483,647。如果数值超出该范围,它会“回绕”或变成负数,导致意外行为。
用户提供的或不受信任的输入
依赖用户输入来执行整数运算的应用程序(例如计算缓冲区大小、数组索引或对象大小),很容易成为溢出攻击的目标。
例子:一个Web应用程序从用户那里获取输入来分配内存大小(如文件上传或对象存储),并在没有边界检查的情况下进行整数运算。
缺乏输入验证
未检查的用户输入允许攻击者通过精心设计的输入触发溢出条件。如果应用程序没有对输入进行清理或验证,确保其在可接受的范围内,就会引发漏洞。
这种情况常见于文件解析库、网络协议以及图像渲染库中,攻击者可以操纵大型文件或数据维度。
没有边界检查的算术运算
当应用程序执行算术运算(如加法、减法、乘法、除法)时,如果没有检查结果是否在整数的容量范围内,它就容易受到整数溢出的攻击。
应用程序在处理诸如缓冲区大小、内存分配、数组索引等数学计算时,风险较高。
示例
void copy_data(int size) { char *buf = malloc(size + 10); // Potential overflow if size is close to INT_MAX ...}
内存管理和动态分配
使用动态内存分配(如C/C++中的malloc()calloc())并基于整数运算计算内存大小的应用程序容易受到溢出攻击。计算错误的内存大小可能会分配比预期更少的内存,导致缓冲区溢出或内存损坏。
例子:在为大数据集分配动态缓冲区时,由于乘法运算的溢出导致的内存计算错误。
基于整数值的安全关键决策
某些应用依赖整数值进行安全检查(如访问控制、大小验证或边界检查)。如果这些值发生溢出,可能会导致绕过这些安全措施。
例子:如果一个应用使用有符号整数进行访问控制(负数代表“无访问权限”,正数代表“完全访问权限”),整数溢出可能会将一个非常大的正数绕回为一个小数或负数,从而绕过安全检查。
遗留代码或系统
使用C/C++等语言编写的旧应用程序更容易受到整数溢出问题的影响,因为它们直接使用底层整数运算。遗留系统通常使用范围有限的数据类型,使其更加脆弱。
低级编程语言(C/C++,汇编)
使用低级语言(如C/C++)编写的应用程序由于其直接的内存管理和缺乏自动溢出处理,固有地更容易受到整数溢出漏洞的影响。在高级语言中,溢出可能会被捕获,但在C/C++中,程序行为通常是未定义的,可能会被利用。
图形、多媒体和文件处理库
处理多媒体(图像、视频、音频)或文件格式的应用程序或库通常是整数溢出攻击的目标。这些库通常需要处理大文件和数组,尺寸或长度计算错误可能导致溢出。
例子:在图像解析库中,计算图像尺寸或像素大小时的整数溢出可能导致内存损坏。
网络协议和数据包处理
处理网络协议数据包的应用程序通常涉及长度和偏移的计算。在这些上下文中的整数溢出可能导致数据包的错误处理,从而使攻击者可以执行任意代码或使系统崩溃。
例子:在计算数据包长度时的整数溢出可能使一个格式错误的数据包触发数据包处理程序中的缓冲区溢出。

易受攻击的应用程序示例:

1.Web应用程序:如果Web应用程序在执行算术运算前没有验证输入(如文件上传、分页和对象大小),它们可能会受到整数溢出攻击,这可能导致服务拒绝(DoS)或被攻击。
2.媒体播放器和图像查看器:许多图像处理(如解析PNG、GIF、JPEG文件)或媒体播放器的漏洞来自于尺寸或文件大小计算中的整数溢出。攻击者可能会伪造恶意的媒体文件以利用这些漏洞。
3.文件系统和压缩软件:处理压缩数据或文件系统的应用程序,如zip/tar/unzip工具,在计算压缩或解压缩数据大小时可能会发生整数溢出,导致溢出和随后的内存损坏。
4.加密库:执行复杂数学运算的加密库(如OpenSSLGnuTLS)如果在进行操作(如模运算)时没有正确检查溢出条件,可能会受到攻击。
5.游戏引擎和图形引擎:处理大量图形数据(如纹理、坐标或对象)的游戏引擎容易受到整数溢出攻击。攻击者可能会利用游戏引擎或图形引擎中的漏洞触发意外行为或崩溃。

导致漏洞的条件:

缺乏保护机制:代码中没有明确的溢出检查。
用户可控的大值:直接使用用户输入进行大小或内存分配计算的情况。
复杂的计算:算法涉及复杂的整数运算而未验证结果。

整数溢出漏洞的影响

整数溢出的影响取决于其发生的上下文、受影响的应用程序以及攻击者可以如何利用它。其影响范围广泛,从简单的应用程序崩溃到严重的后果,如任意代码执行权限提升服务拒绝(DoS)。以下是对各种影响的分解:
内存损坏:可能导致崩溃、意外行为或恶意控制程序的执行。
缓冲区溢出:可能覆盖关键内存区域,导致代码执行或应用崩溃。
服务拒绝(DoS):导致应用崩溃,系统对用户不可用。
任意代码执行:攻击者控制程序的执行流程,通常导致系统完全妥协。
绕过安全检查:关键边界和权限检查可能被绕过,导致安全漏洞。
权限提升:攻击者可以获得更高的系统权限,破坏安全性。
逻辑错误:错误的计算和行为,尤其在金融或关键任务应用程序中非常危险。
数据损坏:文件系统或数据库损坏可能导致数据丢失和系统性故障。

实例分析:

CVE-2016-1019(Adobe Flash Player)
影响:此整数溢出漏洞允许攻击者通过特制的SWF文件触发内存损坏,进而实现远程代码执行。
后果:攻击者可以通过嵌入恶意Flash内容的网站或广告来执行任意代码,导致大规模利用。
CVE-2008-0015(OpenSSL)
影响:OpenSSL的ASN.1解析器中的整数溢出导致内存损坏并可能执行代码。
后果:攻击者可以使系统崩溃或可能执行任意代码,这是加密生态系统中的一个重大漏洞。
CVE-2020-26950(Mozilla Firefox)
影响:Firefox中的整数溢出允许攻击者通过特制的网页内容触发内存损坏,从而导致远程代码执行漏洞。
后果:此漏洞可能用于驱动式攻击,仅访问恶意网站即可危及浏览器及底层系统。

实践演示

接下来,我们将创建一个示例应用程序,以展示整数溢出漏洞及其影响。该程序将包含几个部分,这些部分故意遭受整数溢出漏洞,并触发内存损坏、缓冲区溢出、服务拒绝和潜在代码执行等场景。
方法
我们将构建一个具有以下结构的应用程序:
1.未进行边界检查的算术运算:演示由于未检查操作导致的溢出。
2.基于溢出值的动态内存分配:展示溢出如何导致缓冲区溢出和内存损坏。
3.安全检查绕过:演示溢出如何使攻击者绕过安全检查。
4.服务拒绝(DoS):通过触发崩溃或资源耗尽来实现。
5.权限提升模拟:说明溢出如何导致错误的权限分配。
以下是一个包含多个易受整数溢出影响的函数的C++程序。
#include <iostream>#include <cstring>#include <limits>#include <cstdlib>using namespace std;// Vulnerability: Integer overflow in a memory allocation calculationvoid memory_allocation_overflow(int input) { int size = input * sizeof(int); // Multiplication overflow cout << "Allocating memory for: " << size << " bytesn"; int *buffer = (int *)malloc(size); if (buffer == nullptr) { cout << "Memory allocation failedn"; return; } // Simulate a memory write operation for (int i = 0; i < input; i++) { buffer[i] = i; // Buffer overflow if size is incorrectly allocated } cout << "Buffer populatedn"; free(buffer);}// Vulnerability: Integer overflow in security check leading to security bypassvoid privilege_check(int user_id) { int max_allowed_id = 1000; // Max allowed ID is 1000 if (user_id > max_allowed_id) { cout << "Access denied for user ID: " << user_id << endl; } else { cout << "Access granted for user ID: " << user_id << endl; }}// Vulnerability: Denial of service due to large integer valuevoid large_allocation(int size) { // Large allocation with integer overflow int *large_array = (int *)malloc(size * sizeof(int)); if (large_array == nullptr) { cout << "Failed to allocate large arrayn"; return; } for (int i = 0; i < size; i++) { large_array[i] = i; // Filling the array } cout << "Large array populatedn"; free(large_array);}// Vulnerability: Arithmetic overflow in logic operationvoid logic_overflow(int count) { int result = count * 1000; // Overflow in multiplication cout << "Calculated result: " << result << endl; if (result < 0) { cout << "Overflow occurred! Unexpected negative value: " << result << endl; } else { cout << "Normal operation, result: " << result << endl; }}// Simulating buffer overflow leading to potential code execution (simplified)void buffer_overflow() { char buffer[10]; cout << "Enter input for buffer (limit 10 characters): "; cin >> buffer; // Buffer overflow if input exceeds 10 chars cout << "You entered: " << buffer << endl;}// Main function to run testsint main() { cout << "n--- Memory Allocation Overflow ---n"; int large_input = std::numeric_limits<int>::max() / 2; // Large input to trigger overflow memory_allocation_overflow(large_input); cout << "n--- Privilege Bypass via Overflow ---n"; int user_id = 2147483647; // Overflowed value simulates bypass privilege_check(user_id); cout << "n--- Denial of Service ---n"; large_allocation(1073741824); // Large allocation leading to DoS cout << "n--- Arithmetic Logic Overflow ---n"; logic_overflow(2147483); // Input causing arithmetic overflow cout << "n--- Buffer Overflow Simulation ---n"; buffer_overflow(); return 0;}
该提供的代码以紧凑的方式展示了各种整数溢出漏洞。它涵盖了内存分配溢出,其中大值导致不正确的缓冲区大小(memory_allocation_overflow),通过不当的用户ID检查实现的权限绕过(privilege_check),以及由于过量内存分配导致的服务拒绝(large_allocation)。logic_overflow函数展示了未经检查的乘法引发的算术溢出,而buffer_overflow则通过接受超过固定缓冲区大小的输入来模拟输入相关的缓冲区溢出。代码部分重点展示了动态内存管理、权限验证和算术运算中典型的溢出场景,这些都是软件安全中至关重要的。

影响探讨

现在让我们逐个分析前面程序中的每个代码块,通过提供适当的输入来解释整数溢出漏洞的影响。
1.内存分配溢出
void memory_allocation_overflow(int input) { int size = input * sizeof(int); // Multiplication overflow cout << "Allocating memory for: " << size << " bytesn"; int *buffer = (int *)malloc(size); if (buffer == nullptr) { cout << "Memory allocation failedn"; return; } // Simulate a memory write operation for (int i = 0; i < input; i++) { buffer[i] = i; // Buffer overflow if size is incorrectly allocated } cout << "Buffer populatedn"; free(buffer);}
输入和影响:
输入: 一个大整数值,例如 2147483647 / 2(即 1073741823),当与 sizeof(int) 相乘时,可能会超过最大整数限制。
影响: 这会导致 size 由于整数溢出而回绕到负值或小的正值,从而导致内存分配不足。当代码尝试写入超出分配的缓冲区时,可能会覆盖相邻内存,导致潜在的崩溃、数据损坏或被攻击者利用。
2. 通过整数溢出绕过权限检查
void privilege_check(int user_id) { int max_allowed_id = 1000; // Max allowed ID is 1000 if (user_id > max_allowed_id) { cout << "Access denied for user ID: " << user_id << endl; } else { cout << "Access granted for user ID: " << user_id << endl; }}
输入和影响:
输入: 一个整数值 2147483647(32 位有符号整数的最大值)。
影响: 由于 user_id 大于 max_allowed_id,条件检查按预期工作。然而,如果应用程序有其他检查或使用不同的逻辑涉及溢出(例如,调整 user_id),这可能导致意外的访问,允许未授权用户获得更高权限或绕过限制。
3. 通过大内存分配引发的服务拒绝(DoS)
void large_allocation(int size) { int *large_array = (int *)malloc(size * sizeof(int)); if (large_array == nullptr) { cout << "Failed to allocate large arrayn"; return; } for (int i = 0; i < size; i++) { large_array[i] = i; // Filling the array } cout << "Large array populatedn"; free(large_array);}
输入和影响:
输入: 一个大整数值,例如 1000000,用于乘法运算。
影响: 在 logic_overflow 函数中,执行 value * value 时,结果会超出 32 位有符号整数的最大值。由于没有边界检查,这将导致溢出,使得 result 变为负值或小于预期的值,从而可能导致逻辑错误或应用程序异常行为。
4. 输入相关的缓冲区溢出
void logic_overflow(int count) { int result = count * 1000; // Overflow in multiplication cout << "Calculated result: " << result << endl; if (result < 0) { cout << "Overflow occurred! Unexpected negative value: " << result << endl; } else { cout << "Normal operation, result: " << result << endl; }}
输入与影响:
输入: 一个值,例如 2147483647 / 1000(或 2147483),在乘以 1000 时会导致溢出。
影响: 这将导致 result 变为负值,表明发生了溢出。根据该结果在程序后续使用的方式(例如,作为迭代或资源分配的限制),可能会导致程序行为不正确、崩溃,或由于处理了意外值而引发安全漏洞。
5.缓冲区溢出模拟
void buffer_overflow() { char buffer[10]; cout << "Enter input for buffer (limit 10 characters): "; cin >> buffer; // Buffer overflow if input exceeds 10 chars cout << "You entered: " << buffer << endl;}
输入与影响:
输入: 一个长度超过 10 个字符的字符串,例如 "ThisIsDefinitelyMoreThanTenCharacters"
影响: 超出缓冲区大小的输入可能会覆盖相邻的内存,导致缓冲区溢出。这可能导致程序崩溃、数据损坏,或者如果攻击者利用此溢出来改变程序的执行流程,则可能执行任意代码。
以上内容由白帽子左一翻译并整理。原文:https://infosecwriteups.com/exploring-integer-overflow-the-realm-of-exploiting-binaries-706d4f7f174e

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。

原文始发于微信公众号(白帽子左一):二进制漏洞利用 | 整数溢出探究

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月16日18:02:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   二进制漏洞利用 | 整数溢出探究https://cn-sec.com/archives/3275877.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息