应用安全系列之三十四:数值溢出
应用程序中难免会遇到数字的处理,针对数字的处理如果不当也会造成严重的问题,著名的Heartbleed漏洞也是没有验证数字的有效性导致的。
数值处理不好的,轻则产生异常,重则影响整个程序的正常运行,因此,针对由数值导致的问题也不能掉以轻心。主要问题总结为以下几点:
1) 异常
当从请求中获取参数的值需要转成数字时,这是就可能产生异常,产生异常的原因:一、内容符合数值的要求,含有异常字符;二、数值超出了数值类型的范围。如一下代码:
public static void main(String[] args) {int value = Integer.parseInt("9147483647");System.out.println("the int value is"+value);}
当数值超过类型的最大值时,就会抛出异常信息如下:
同样,当数值含有不合法的字符时,抛出的异常也是一样的:
因此再接受数值的数据时,需要注意捕捉NumberFormatException这个异常,以防,程序在出异常后,直接跳出程序。
2) DOS
当数值被用于创建或者申请资源时,这时就需要注意验证数值的有效范围,例如:当一个数值是从客户端的搜索页面传递而来的,这个数值是用于指示搜索的一个页面显示多少条记录,通常这个数值的是几个常用的数字【10,50,100】;,但是当这个数值被修改为10000或者更大的数字而且符合条件的数据又恰好很多时,服务器如果直接根据这个数值去数据库查询所有记录,并组装成响应消息返回,就会消耗很多资源,特别是内存资源。曾经在渗透的测试过程中,遇到过一个页面通过查询返回了近7000条数据,而且花了很长时间页面才显示正常。
在使用C或者C++时,如果使用攻击者可以控制的数字来分配内存,就会直接导致更严重的问题,例如:内存溢出、分配内存失败或者读内存失败导致的程序运行异常,直接可以导致程序中断运行直接退出。
3) 信息泄露
Heartbleed漏洞就是典型的信息泄露的最好的例子,由于在读取内存时,没有判断数值的有效范围,导致在复制内存时,复制了超越实际范围的内存,使得攻击者可以通过此漏洞读取服务器端内存的内容,如果内存中含有用户登录相关的信息,攻击者就可以直接获取登录的会话信息劫持会话。HeartBleed的实例代码如下:
int dtls1_process_heartbeat(SSL *s){unsigned char *p = &s->s3->rrec.data[0], *pl;unsigned short hbtype;unsigned int payload;unsigned int padding = 16; /* Use minimum padding *//* Read type and payload length first */
hbtype = *p++;n2s(p, payload);pl = p;//do something with the payloadif (s->msg_callback)s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,&s->s3->rrec.data[0], s->s3->rrec.length,s, s->msg_callback_arg);if (hbtype == TLS1_HB_REQUEST){unsigned char *buffer, *bp;int r;/* Allocate memory for the response, size is 1 byte* message type, plus 2 bytes payload length, plus* payload, plus padding*/buffer = OPENSSL_malloc(1 + 2 + payload + padding);//allocate all that memory without any checksbp = buffer;/* Enter response type, length and copy payload */*bp++ = TLS1_HB_RESPONSE;s2n(payload, bp);memcpy(bp, pl, payload);bp += payload;/* Random padding */RAND_pseudo_bytes(bp, padding);r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);//send the response back, even the stuff the attacker wasn't supposed to seeif (r >= 0 && s->msg_callback)s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,buffer, 3 + payload + padding,s, s->msg_callback_arg);OPENSSL_free(buffer);if (r tlsext_hb_seq){dtls1_stop_timer(s);s->tlsext_hb_seq++;s->tlsext_hb_pending = 0;}}return 0;}
从代码中可以看到从SSL中获取payload之后,没有做任何验证,直接用于:buffer = OPENSSL_malloc(1 + 2 + payload + padding)分配内存,并且用于复制内存。修改之后的代码如下:
int dtls1_process_heartbeat(SSL *s)
{
unsigned char *p = &s->s3->rrec.data[0], *pl;
unsigned short hbtype;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */if (s->msg_callback)
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
&s->s3->rrec.data[0], s->s3->rrec.length,
s, s->msg_callback_arg);/* Read type and payload length first */
if (1 + 2 + 16 > s->s3->rrec.length)
return 0; /* silently discard */
hbtype = *p++;
n2s(p, payload);
if (1 + 2 + payload + 16 > s->s3->rrec.length)
return 0; /* silently discard per RFC 6520 sec. 4 */
pl = p;
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;
unsigned int write_length = 1 /* heartbeat type */ +
2 /* heartbeat length */ +
payload + padding;
int r;if (write_length > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(write_length);
bp = buffer;/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
s2n(payload, bp);
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
RAND_pseudo_bytes(bp, padding);r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);if (r >= 0 && s->msg_callback)
s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,
buffer, write_length,
s, s->msg_callback_arg);OPENSSL_free(buffer);if (r tlsext_hb_seq)
{
dtls1_stop_timer(s);
s->tlsext_hb_seq++;
s->tlsext_hb_pending = 0;
}
}return 0;
}
在if
(1 + 2 + payload + 16 > s->s3->rrec.length)队payload增加了检查。
当应用程序因为数字处理不当时导致异常被是直接回显到页面时,也会导致信息泄露【可以参考应用安全系列之三十一:信息泄露_jimmyleeee的博客-CSDN博客】。
4) 除零操作
如果进行除法或者取余操作时,没有判断数值的有效性,会导致除零异常。在Java如果有除零发生时,抛出的异常如下:
有的语言也可能会导致程序崩溃,进而也导致DOS攻击的发生。
5) 溢出
数值操作最容易犯的错误还是溢出的问题,无论使用任何语言,都会有堆数值类型的加减乘除操作,在操作时,如果没有类型使用不当可能会导致数值溢出的问题发生。如下Java代码:
public static void main(String[] args) {int overflow = Integer.MAX_VALUE + 10;System.out.println("the overflow value is"+overflow);}
此程序运行的结果是:
可以看出显示的结果是一个负的值。在C、C++语言中,因为有unsigned int无符号整型,结果值就会是一个很大的值,针对无符号整型,还会产生环绕问题,就是溢出之后,变成0或者一个很小的数值,这个值一旦用于用于分配资源操作或者作为业务逻辑的参数,就会导致结果严重偏离实际的操作。
提别是进行减法运算时,如果没有检查减数的合法性,更容易导致溢出问题的发生,可以根据需求转成加法操作,例如,需要判断a-b是否大于c,可以改成a是否大于b+c等。
对于Java语言而言每种类型的定义里都有一个最大值和最小值,可以使用此最大值来判断数值是否可能会产生溢出:
在数值的实际操作时,也需要根据类型操作的结果的可能范围,将结果的类型设置为一个更大的范围的类型,就会避免溢出的发生。例如:两个int相加的结果,类型设置为long型,操作的结果可能超出int型的最大值,但是,绝对不可能超出long型的范围。
6) 截断
当一个高精度的数值存入到低精度的数值时可能会导致数值被截断,截断之后的值可能会变小,也可能会变成负值,这需要根据被赋值变量的类型而定。示例如下:
public static void main(String[] args) {long value = Long.MAX_VALUE;System.out.println("before cut off value is"+value);int cutoff = (int) value;System.out.println("After cut off value is"+cutoff);}
运行结果显示如下:
由上可见,数值如果处理不好对系统影响也非常大,因此,在数值处理时需要记住以下几点,以防数值操作导致结果不符合预期:
- 在使用数值之前判断其是否在预期的合法范围之内;
- 避免将高精度类型转换成低精度类型,大范围的数值类型转成小范围的数值类型;
- 定义变量时,根据可能的取值范围选择合适的类型;【也不是越大越好,越大占用的内存就大,计算时消耗的CPU资源也大】;
- 在进行计算时,尝试使用不容易出错的运算符,例如:将减法转换成加法;
应用安全系列之三十四:数值溢出相关推荐
- 网络安全系列之三十五 缓冲区溢出
缓冲区溢出的大名可谓如雷贯耳,我们不必去探究缓冲区溢出的原理,只需知道他能做什么就可以了.如果能够成功地对远程计算机进行缓冲区溢出,那么就可以获得远程计算机的Shell,也就可以直接以管理员的身份在远 ...
- IT职场人生系列之十四:经验积累
本文是IT职场人生系列的第十四篇. 任何时候都会发现IT业是个变化迅速的行业,几年前还很时髦的技术,现在已经过时了:几年前还很热门的行业,现在也过时了.这种变化之莫测,别说我们普通人,连IT巨头们都经 ...
- SAP UI5 应用开发教程之三十四 - SAP UI5 应用基于设备类型的页面适配功能(Device Adaptation)试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...
- 《神探tcpdump第五招》-linux命令五分钟系列之三十九
== [系列文章] <神探tcpdump第一招>-linux命令五分钟系列之三十五 <神探tcpdump第二招>-linux命令五分钟系列之三十六 <神探tcpdump第 ...
- Debezium报错处理系列之三十六:Task threw an uncaught and unrecoverable exception. Task is being killed and will
Debezium报错处理系列之三十六:Task threw an uncaught and unrecoverable exception. Task is being killed and will ...
- Debezium报错处理系列之三十八:Timeout expired while fetching topic metadata
Debezium报错处理系列之三十八:'trace': 'org.apache.kafka.common.errors.TimeoutException: Timeout expired while ...
- 软考高级信息系统项目管理师系列之三十五:组织级项目管理
软考高级信息系统项目管理师系列之三十五:组织级项目管理 一.组织级项目管理内容 二.组织级项目管理概述 三.组织级项目管理对战略的支持 四.组织级项目管理框架内容 五.成熟度模型 组织级项目管理知识包 ...
- springboot mybatis ehcache_SpringBoot入门建站全系列(十四)集成Redis缓存
SpringBoot入门建站全系列(十四)集成Redis缓存 一.概述 本地缓存,就是使用应用内使用本地内存将数据暂缓存储,一般数据库的查询如果不怎么改动,可以用本地缓存暂存. 远程缓存,比如redi ...
- ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中)
ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中) 接上文 上文中讲到配置日志模块的第二步,这篇文章继续给大家介绍日志配置方法. Step 3.在</ ...
最新文章
- spring-boot的access日志格式修改
- mysql数据库帐户_MySQL数据库用户帐号管理基础知识详解
- eye caring sticker
- C++的一般引用及其数组引用
- asp与php对比,个人看法 zblogasp和zblogphp的对比
- (转)【MySQL】sync_binlog innodb_flush_log_at_trx_commit 浅析
- Deno 会取代 Node.js 吗?
- java类的扩展注意
- Forms Based Authentication FBA by AD in SharePoint 2010
- Moonbox v0.3beta 发布:Grid 全新重构,更快更解耦
- 10款非常棒的开源论坛系统推荐
- c计算机怎么读音发音英语,英语怎么发音
- mysql误删除数据恢复_mysql误删除数据恢复
- JAVA POI EXCEL导出工具方法 支持冻结列行和设置不可编辑整行整列
- deepin升级Linux内核,深度 deepin 20.1 (1005)系统开启内测:升级至 Linux Kernel 5.8 稳定内核...
- 马踏棋盘问题(C++版)
- 一篇文章说清楚shared_ptr,unique_ptr的区别和关系
- 这个骚网站,它又上新了....
- 让客户在微信上查看订单详情,【单据分享】让你省心又省力!
- 期货模拟和仿真的区别(模拟期货与实盘期货区别)