引言

在数字化时代,软件代码中敏感信息的保护变得尤为重要。敏感信息如密码、令牌和API密钥等,一旦泄露,可能会导致严重的安全问题。
一般安全扫描工具会通过正则表达式进行规则匹配,因为是有限的已知规则模式,这在面对复杂的代码库时可能会产生误报和漏报。本文介绍一种可以与规则匹配相结合的补充方法,即利用信息熵技术来识别代码中的高熵值字符串,并通过大型语言模型(LLM)进一步判断这些字符串是否为敏感信息。

信息熵的概念

信息熵,由克劳德·香农在1948年首次提出,是衡量信息量的一个度量。在信息论中,熵用来描述信源的不确定性或随机性。对于一个随机变量,其熵越高,表示其输出结果的不确定性越大。在自然语言处理中,熵常用于评估文本的复杂性和预测难度。

信息熵在代码分析中的应用

信息熵在代码分析中的应用有很多方面,包括不限于恶意代码检测,代码复杂度分析,代码相似性分析等。本文主要介绍通过信息熵算法来筛选潜在包含敏感信息的代码片段。信息熵可以有效识别随机生成的敏感信息,敏感信息如API密钥、密码等因为是随机生成的,所以具有较高的信息熵,通过计算目标代码的信息熵值,可以判断其是否具有潜在的敏感性。信息熵技术可以作为一种补充方法,与规则匹配方法结合使用,提高敏感信息检测的准确性。

算法执行流程

第一步首先会将目标代码输入算法引擎进行代码熵值的计算;然后第二步根据计算出来的熵值,选择合适的阈值筛选具有高熵值的代码行,最后第三步对筛选出来的代码行进行预处理后发送到LLM,由LLM识别并分类敏感信息,下文会对涉及的三个步骤进行详细叙述。

代码熵值的计算

在代码分析中,我们可以将每一行代码视为一个信源,计算其熵值。字符串的熵值可以通过以下步骤计算:

1.字符频率统计,统计字符串中每个字符出现的频率。
2.概率分布计算,根据字符频率计算每个字符出现的概率。
3.熵值计算,应用香农熵公式计算字符串的熵值。
以下是简单的python代码示例(LLM提供):

from collections import Counter
from math import log2

def calculate_entropy(s):
# 使用 Counter 对字符串 s 中的每个字符进行计数
counts = Counter(s)
# 计算字符串 s 的总长度
total = len(s)
# 计算每个字符的概率
probabilities = [count / total for count in counts.values()]
# 计算信息熵
    entropy = -sum(p * log2(p) for p in probabilities if p > 0)
    return entropy
高熵值代码行的识别

在对代码库中每一行代码计算熵值后,我们可以通过设定的特定阈值或阈值范围识别出那些熵值高于特定阈值或者在特定阈值范围内的代码行,之所以不单单指定特定阈值,是因为信息熵算法只是计算熵值,而有些普通的代码行其本身阈值也可能很高,这样就会产生不必要的误报。
这个过程中很重要的一个关键点是对阈值的选择,这里提出几个方法用作参考。

  1. 统计分析,计算所有代码行的信息熵后,通过分析熵值分布,选择合适的熵值。
  2. 经验规则,根据已有经验和启发式规则,人为定义合适的阈值范围。
  3. 机器学习,收集大量的各类别的敏感信息,通过机器学习计算出一个合适的阈值范围,对于密钥等敏感信息,其分布很可能存在一个相似的阈值范围,这样比单独指定特定阈值会提高检测的准确性,同时减少使用LLM的成本。
大模型在敏感信息检测中的作用

对于识别出的高熵值代码行,我们可以将其输入到LLM中,以判断这些字符串是否为敏感信息,是什么敏感信息。
LLM通过学习大量的文本数据,能够理解和生成自然语言,我们筛选出的这些代码行其本质也是文本数据,基于提示工程,通过合适的提示技巧LLM可以用于识别敏感信息的任务,尤其是经过微调后的专用识别敏感信息的LLM。
其实也可以将整个代码库直接发送到LLM进行识别,但一方面来说文本复杂度挺高的,提高了LLM的识别难度;另一方面,这样的做法发送的token也蛮多的,大大增加了LLM的使用成本。
下面是Python使用LLM的伪码示例:

def check_sensitive_info(string):
    #对代码字符串进行预处理
     code_string = pre_process(string)
    # 这里调用LLM的API进行判断
response = large_language_model_api.predict(string)
#对LLM返回的数据进行格式处理
info = post_process(response)
    return info

算法的使用场景

安全左移的思想在今天也不是什么新鲜的事物,其体现就是SDL和DEVSECOPS。
简单描述下SDL的相关理念,至于后者也大差不差,两者的区别就在于后者高度的自动化,更符合基于云原生的敏捷软件开发,可以高迭代的进行CI/CD。
SDL就是希望软件可以增加一个安全属性,期望软件开发生命周期中增加一个安全的维度指导软件开发,具体的做法就是将安全实践活动融合进软件开发的生命周期,安全实践活动是指安全任务的集合,而安全任务就是针对安全需求的解决方案,安全需求就是我们常说的那些潜在的安全威胁,对应到我们本文的主题就是硬编码在源码中的敏感信息。
那检测敏感信息的安全任务可以集成到SDL的哪些环节呢,自然是越早越好,越早其修复所占用的成本越低。所以最好的情况是程序员遵守安全编码规范,直接省掉检测环节,一般来说可以将具备敏感信息检测能力的IAST(交互式应用安全测试工具)插件集成到程序员使用的IDE中,在程序员编写代码的同时提示其可能存在的敏感信息,或者在程序员提交代码时,可以将代码放到暂存仓库,设置对暂存代码仓库的扫描,不符合扫描要求的代码退回整改,最后就是上线前或上线后对整体的产品进行扫描了,另外,还要建立常规的扫描策略,对软件进行定期的扫描,实时监控代码仓库的变更和敏感信息泄露等。

结论

本文提出了一种结合信息熵和LLM的方法,用于检测代码中的敏感信息,虽然该方法作为一种补充方法可以一定程度提高准确性,但也存在一些局限。例如,信息熵算法基于熵值筛选代码行,但可能因为某些代码行的熵值与敏感信息的熵值接近而产生误报;LLM可能对某些类型的敏感信息不够敏感,或者在处理特定编程语言的语法时存在困难等。不过随着技术的发展,这种方法有望成为保护软件代码安全的一种较为完善的技术。