Java常见漏洞——整数溢出漏洞、硬编码密码漏洞、不安全的随机数生成器
创始人
2024-03-03 20:07:38
0

目录

前言:

(一)整数溢出漏洞

0x01 整数溢出漏洞介绍

1.1  上界溢出

1.2 下界溢出

0x02 整数溢出漏洞修复

(二)硬编码密码漏洞

修复案例:

(三)不安全的随机数生成器


前言:

        本次总结的漏洞在实战情况下,可能只是一个环节,包括我们经常遇到的WAF绕过,技术偏逆向破解,但是在web渗透测试中有一定的利用价值。

(一)整数溢出漏洞


        计算机程序中的整数都是有范围的,不同的数据类型范围也不同,这是由编译器决定的,超过这个范围就有可能会出现整数溢出的情况。         比如说Java 的 int 是 32 位有符号整数类型,其最大值是 0x7fffffff ,最小值是0x80000000,即 int 表示的数的范围是在-2147483648 ~ 2147483647 之间。当 int 类型的运算结果超出了这个范围时则发生了溢出,而且不会有任何异常抛出。整数溢出一般可以分为上界溢出和下界溢出两种。

0x01 整数溢出漏洞介绍


1.1  上界溢出

      int 类型二进制存储的第一位为符号位,0 表示正数,1 表示负数,2147483647 这个数字的二进制表达为 01111111 11111111 11111111 11111111,加 1 以后的值为 10000000 00000000 00000000 00000000,发生上界溢出,而 10000000 00000000 00000000 00000000 表示的是-2147483648 这个数字

1.2 下界溢出

        int 类型二进制存储的第一位为符号位,0 表示正数,1 表示负数,-2147483648 这个 数字的二进制表达为 10000000 00000000 00000000 00000000,减 1 以后的值为 01111111 11111111 11111111 11111111,发生下界溢出,而 01111111 11111111 11111111 11111111 表示 的是 2147483647 这个数字。Java 程序溢出运行的案例如图 1-1 所示:

1  

图 1-1  Java 程序溢出运行的案例

0x02 整数溢出漏洞修复


在 Java 8 版本中,可以使用新的“Math#addExact() and Math#subtractExact()”方法,该方法将监测“ArithmeticException”溢出
public static boolean willAdditionOverflow(int left, int right) { try { Math.addExact(left, right); return false; } catch (ArithmeticException e) { return true; } } 
public static boolean willSubtractionOverflow(int left, int right) { try { Math.subtractExact(left, right); return false; } catch (ArithmeticException e) { return true; } 
}

(二)硬编码密码漏洞


硬编码密码是指在系统中采用明文的形式存储密码,通常会导致严重的身份验证失败,这对于系统管理员而言可能很难检测到,一旦检测到,也很难修复。硬编码密码会造成密码泄露,其主要出现在以下几个方面
  1. 开发人员的安全意识不强:将代码托管到 github 等互联网平台,可能会造成源代码泄露,任何有该代码权限的人都能读取此密码。
  2. 程序员可以简单地将后端凭证硬编码前端软件中:该程序的任何用户都可以提取密码。因为从二进制文件中提取密码非常简单,所以会对带有硬编码密码的客户端系统构成很大的威胁。
         以下代码是使用硬编码的密码连接到数据库的示例:
DriverManager.getConnection(url,"scott","tiger");
        攻击者可以通过 javap –c 命令来访问反汇编的代码,反汇编的代码将包含所使用的密码值。

javap -c ConnMngr.class 
22: ldc #36; //String jdbc:mysql://ixne.com/rxsql 
24: ldc #38; //String scott 
26: ldc #17; //String tiger
        程序员在编写程序时应尽量避免对密码进行硬编码,而采用对密码加以模糊化或先经过 hash 处理再存储,或在外部资源文件中进行处理的方法。

修复案例:

        在上述修复代码中,首先将数据库连接的用户名密码加密放入 db.properties 文件中,如图 1-2 所示

 

图 1-2 用户名密码先加密放入 db.properties 文件中
      
     然后通过代码读取数据库配置文件,最后进行数据库的连接,这样就避免了硬编码产生的漏洞。
        示例:读取 properties 属性文件到输入流中,从输入流中加载属性列表,获取数据库连接属性值,然后进行数据库连接,这样就不会出现硬编码漏洞了。

// 读取 properties 属性文件到输入流中
InputStream is = PropertiesTest.class.getResourceAsStream("/db.properties"); 
// 从输入流中加载属性列表
properties.load(is); 
// 获取数据库连接属性值
DRIVER_CLASS = properties.getProperty("DRIVER_CLASS"); 
DB_URL = properties.getProperty("DB_URL"); 
DB_USER = properties.getProperty("DB_USER"); 
DB_PASSWORD = properties.getProperty("DB_PASSWORD"); 
// 加载数据库驱动类
Class.forName(DRIVER_CLASS);

(三)不安全的随机数生成器


随机数是专门的随机试验的结果。产生随机数有多种不同的方法,这些方法被称为随机数发生器。随机数最重要的特性是:它所产生的后面的那个数与前面的那个数毫无关系。根据密码学原理,随机数生成器分为以下三类。
  1. 统计学伪随机数生成器(PRNG):伪随机数生成器从一个初始化的种子值开始计算得到序列,从种子开始,然后从种子中计算出后续值,当种子确定后生成的随机数也是确定的,但其输出结果很容易预测,因此容易复制数值流。
  2. 密码学安全随机数生成器(CSPRNG):密码学安全伪随机性是统计学伪随机数生成器的一个特例,给定随机样本的一部分和随机算法,不能有效地演算出随机样本的剩余部分。
  3. 真随机数生成器:其定义为随机样本不可重现。实际上只要给定边界条件,真随机数并不存在。可是如果产生一个真随机数样本的边界条件十分复杂且难以捕捉(比如计算机当地的本底辐射波动值),则可以认为用这个方法演算出来了真随机数。

        使用计算机产生真随机数的方法是获取 CPU 频率与温度的不确定性,以及统计一段时间内的运算次数每次都会产生不同的值,系统时间的误差以及声卡的底噪等。在实际应用中往往使用伪随机数就足够了。计算机或计算器产生的随机数有很长的周期性。实际上它们不真正地随机,因为它们是可以计算出来的,但是它们具有类似于随机数的统计特征。这样的发生器称为伪随机数发器。

        Java 中的“java.util.Random”工具类 LCG 线性同余法伪随机数生成器,可以根据种子和算法生成随机数。此算法的缺陷就是可预测性,攻击者可能会猜测将要生成的下一个值,并使用此猜测来模拟其他用户或访问敏感信息。“java.util.Random”工具类没带参数构造函数生成的 Random 对象的种子默认是当前系统时间的毫秒数,故进入到 Random 类中查看其种子默认是当前的系统时间,如图 3-1 所示。
图 3-1 进入 Random 类中查看其种子默认是当前的系统时间
Random 函数的使用方式:
Random random = new Random(); 
int r = random.nextInt(); // 生成一个随机数

 只要种子一样,其输出的随机序列也是一样的,如设置两个随机数列种子都是 1,则输出的随机数列也是完全相同的,如图 3-2 所示。

图 3-2 随机数列种子一样,其输出的随机序列也一样

 

        “java.util.Random”不是加密安全的。可以使用 SecureRandom 来获取密码安全的伪随机数生成器,以供对安全敏感的应用程序使用。“java.Security.SecureRandom”工具类提供加密的强随机数生成器(RNG),要求种子必须是不可预知的,产生非确定性输出。操作系统收集了一些随机事件,比如鼠标点击、键盘点击,等等。SecureRandom 使用这些随机事件作为种子。SecureRandom 函数的使用方式:
SecureRandom secureRandom2 = SecureRandom.getInstance("SHA1PRNG"); 
int r = secureRandom2.nextInt(); // 生成一个随机数
使用 SecureRandom 生成伪随机,因为 SecureRandom 使用鼠标点击、键盘点击等等这些随机事件作为种子,故其生成的随机数列完全不同,安全性要高,所以建议使用 “java.Security.SecureRandom”工具类来代替“java.util.Random”工具类,如图 3-3 所示。
图 3-3 使用 java.Security.SecureRandom 工具类生成随机数序列

 

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...