应用程序中难免会遇到数字的处理,针对数字的处理如果不当也会造成严重的问题,著名的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资源也大】;
  • 在进行计算时,尝试使用不容易出错的运算符,例如:将减法转换成加法;

应用安全系列之三十四:数值溢出相关推荐

  1. 网络安全系列之三十五 缓冲区溢出

    缓冲区溢出的大名可谓如雷贯耳,我们不必去探究缓冲区溢出的原理,只需知道他能做什么就可以了.如果能够成功地对远程计算机进行缓冲区溢出,那么就可以获得远程计算机的Shell,也就可以直接以管理员的身份在远 ...

  2. IT职场人生系列之十四:经验积累

    本文是IT职场人生系列的第十四篇. 任何时候都会发现IT业是个变化迅速的行业,几年前还很时髦的技术,现在已经过时了:几年前还很热门的行业,现在也过时了.这种变化之莫测,别说我们普通人,连IT巨头们都经 ...

  3. SAP UI5 应用开发教程之三十四 - SAP UI5 应用基于设备类型的页面适配功能(Device Adaptation)试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  4. 《神探tcpdump第五招》-linux命令五分钟系列之三十九

    == [系列文章] <神探tcpdump第一招>-linux命令五分钟系列之三十五 <神探tcpdump第二招>-linux命令五分钟系列之三十六 <神探tcpdump第 ...

  5. 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 ...

  6. Debezium报错处理系列之三十八:Timeout expired while fetching topic metadata

    Debezium报错处理系列之三十八:'trace': 'org.apache.kafka.common.errors.TimeoutException: Timeout expired while ...

  7. 软考高级信息系统项目管理师系列之三十五:组织级项目管理

    软考高级信息系统项目管理师系列之三十五:组织级项目管理 一.组织级项目管理内容 二.组织级项目管理概述 三.组织级项目管理对战略的支持 四.组织级项目管理框架内容 五.成熟度模型 组织级项目管理知识包 ...

  8. springboot mybatis ehcache_SpringBoot入门建站全系列(十四)集成Redis缓存

    SpringBoot入门建站全系列(十四)集成Redis缓存 一.概述 本地缓存,就是使用应用内使用本地内存将数据暂缓存储,一般数据库的查询如果不怎么改动,可以用本地缓存暂存. 远程缓存,比如redi ...

  9. ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中)

    ASP.NET企业开发框架IsLine FrameWork系列之十四--框架配置信息大全(中) 接上文 上文中讲到配置日志模块的第二步,这篇文章继续给大家介绍日志配置方法. Step 3.在</ ...

最新文章

  1. spring-boot的access日志格式修改
  2. mysql数据库帐户_MySQL数据库用户帐号管理基础知识详解
  3. eye caring sticker
  4. C++的一般引用及其数组引用
  5. asp与php对比,个人看法 zblogasp和zblogphp的对比
  6. (转)【MySQL】sync_binlog innodb_flush_log_at_trx_commit 浅析
  7. Deno 会取代 Node.js 吗?
  8. java类的扩展注意
  9. Forms Based Authentication FBA by AD in SharePoint 2010
  10. Moonbox v0.3beta 发布:Grid 全新重构,更快更解耦
  11. 10款非常棒的开源论坛系统推荐
  12. c计算机怎么读音发音英语,英语怎么发音
  13. mysql误删除数据恢复_mysql误删除数据恢复
  14. JAVA POI EXCEL导出工具方法 支持冻结列行和设置不可编辑整行整列
  15. deepin升级Linux内核,深度 deepin 20.1 (1005)系统开启内测:升级至 Linux Kernel 5.8 稳定内核...
  16. 马踏棋盘问题(C++版)
  17. 一篇文章说清楚shared_ptr,unique_ptr的区别和关系
  18. 这个骚网站,它又上新了....
  19. 让客户在微信上查看订单详情,【单据分享】让你省心又省力!
  20. 期货模拟和仿真的区别(模拟期货与实盘期货区别)

热门文章

  1. Python登陆人人网
  2. 相对论【4】一般相对论的普通结果与闵可夫斯基四维空间简单介绍
  3. 数仓、数湖、仓湖一体
  4. 在USA使用交行信用卡的感受
  5. MySQL判断奇数偶数
  6. html+css+javascript搭建个人博客
  7. pxe装机原理_PXE 装机详解
  8. POJ 1679 解题报告
  9. Java岗:2022最新版的Java面试突击班手册,大厂面试轻松拿捏住!
  10. 美日联盟:谷歌夏普联手为VR开发液晶显示器