跳转至

Insecure Dynamic Library Loading

不安全的动态库加载

描述

如果未安全实现动态加载库,可能会引入一系列重大漏洞,对应用程序的安全性和完整性构成严重风险:

不安全的加载路径 (Insecure Loading Path):当应用程序从不受信任或被篡改的位置加载库时,就会出现此漏洞。如果应用程序在不知情的情况下从恶意来源加载库,就会为潜在的攻击敞开大门。攻击者可以利用此弱点将恶意库放置在不受信任的位置,从而导致以提升的权限执行代码或未经授权访问敏感资源。

库劫持 (Library Hijacking):当攻击者用恶意库替换合法库时,就会发生库劫持。通过篡改库加载过程,攻击者可以欺骗应用程序转而加载恶意库。这可以实现广泛的攻击,包括代码注入、权限提升以及未经授权访问敏感数据。

如果不解决这些漏洞,可能会产生严重的后果。攻击者可以将恶意代码注入应用程序,破坏其完整性,未经授权访问关键资源,并可能利用其他安全漏洞。

易受攻击的实现示例:

void loadDependency(String unsanitized_user_input) {
  // 在未对输入进行清理的情况下动态加载库
  final dylib = DynamicLibrary.open(unsanitized_user_input);

  // 解析并调用已加载库中包含恶意代码的函数
  final libraryMethod =
      dylib.lookupFunction<Pointer<Utf8> Function(), Pointer<Utf8> Function()>(
          'getSensitiveData');
  final result = libraryMethod();
}
func loadDynamicLibrary(unsanitized_user_input: String) {

    // 尝试在未对用户输入进行清理的情况下动态加载库 
    if let libraryHandle = dlopen(unsanitized_user_input, RTLD_NOW) {
        // 库加载成功,解析可能包含恶意代码的函数
        if let method = dlsym(libraryHandle, "libraryMethod") {
            typealias FunctionType = @convention(c) () -> String
            let function = unsafeBitCast(libraryMethod, to: FunctionType.self)
            let result = function()
        }
        dlclose(libraryHandle)
    }
}
fun loadDependency(unsanitized_user_input : String) {

    // 动态加载库而未清理输入
    System.load(unsanitized_user_input)

    // 使用动态加载的库执行某些操作
    val result = libraryMethod()
}

建议

在处理动态库加载时,开发人员应该:

  • 实施强大的输入验证和清理技术,以防止目录遍历(directory traversal)和注入攻击。
  • 仅从受信任和已验证的来源加载库,确保库的完整性和真实性。
  • 实施严格的访问控制以防止未经授权加载库。
  • 定期更新库并应用补丁,以解决已知漏洞。
  • 采用强大的代码签名和完整性验证机制,确保动态加载的库的完整性。

安全的实现示例:

void validation(String input){

    // 验证库文件完整性
    Uint8List fileBytes = libraryFile.readAsBytesSync();
    Digest fileDigest = SHA256Digest().process(fileBytes);
    Uint8List expectedChecksum = Uint8List.fromList([...]);

    if (fileDigest.bytes != expectedChecksum) {
        return false; // 文件校验和无效
    }

    if (/* 检查 .. 模式 */ )
        return false; // 路径无效

    // 添加特定于您的实现的其他验证检查
    return true;
}

void loadDependency(String unsanitized_user_input) {

    // 清理用户输入
    if (validation(unsanitized_user_input) == false)
        throw FormatException("invalid input");

    // 使用经过验证的输入动态加载库
    final dylib = DynamicLibrary.open(unsanitized_user_input);

    // 解析并调用已加载库中的函数
    final libraryMethod = 
    dylib.lookupFunction<Pointer<Utf8> Function(), Pointer<Utf8> Function()>(
        'getSensitiveData');
    final result = libraryMethod();
}
func validation(unsanitized_user_input: String){

    guard let fileData = fileManager.contents(atPath: libraryURL.path) else {
        return false // 读取文件数据失败
    }
    let fileDigest = SHA256.hash(data: fileData)

    // 将计算出的校验和与预期校验和进行比较
    let expectedChecksum: [UInt8] = [ /* 替换为您预期的校验和 */ ]
    if fileDigest != expectedChecksum {
        return false // 文件校验和无效

    if (/* 检查 .. 模式 */ )
        return false; // 路径无效

    // 添加特定于您的实现的其他验证检查
    return true;
  }
}

func loadDynamicLibrary(unsanitized_user_input: String) {

    // 验证您的用户输入
    if !validation(unsanitized_user_input){
      throw CustomValidationError.invalidInput
    }

    // 尝试使用经过验证的用户输入动态加载库 
    if let libraryHandle = dlopen(unsanitized_user_input, RTLD_NOW) {
        // 库加载成功,解析可能包含恶意代码的函数
        if let method = dlsym(libraryHandle, "libraryMethod") {
            typealias FunctionType = @convention(c) () -> String
            let function = unsafeBitCast(libraryMethod, to: FunctionType.self)
            let result = function()
        }
        dlclose(libraryHandle)
    }
}
fun validation(input : String){

    // 验证库文件完整性
    val fileBytes = Files.readAllBytes(libraryFile.toPath())
    val digest = MessageDigest.getInstance("SHA-256")
    val fileDigest = digest.digest(fileBytes)
    val expectedChecksum = byteArrayOf(...)

    if (!fileDigest.contentEquals(expectedChecksum)) {
        return false
    }

    if (/* 检查 .. 模式 */ )
        return false  // 路径无效

    // 添加特定于您的实现的其他验证检查
    return true
}

fun loadDependency(unsanitized_user_input : String) {

    // 验证您的用户输入
    if (!validation(unsanitized_user_input))
        throw IllegalArgumentException("Invalid input")

    // 使用经过验证的输入动态加载库
    System.load(unsanitized_user_input)

    // 使用动态加载的库执行某些操作
    val result = libraryMethod()
}

链接

标准

  • OWASP_MASVS_L1:
    • MSTG_PLATFORM_3
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_3
  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_3
    • REQ_11_3
  • OWASP_MASVS_v2_1:
    • MASVS_CODE_4
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
    • SECURITY255