如何通过编译器标志增强移动应用的安全性

server/2024/12/17 19:28:13/

作为一名 Android 或 iOS 开发者,您可能已经熟悉一些常见的安全开发最佳实践,比如验证外部输入、合理管理内存以及避免使用弱加密算法。然而,即便是最精心编写的代码,也可能包含一些 bug,其中一些可能会导致可被利用的安全漏洞,尤其是在使用 C 或 C++ 等语言编写的原生代码中。

多年来,开发了许多防御技术,可以通过简单的编译器标志来启用,而无需修改源代码。这些技术能够有效地提高应用的安全性。在本文中,我们将为您概述一些关键的安全特性,包括:

· 它们防护的攻击类型

· 如何启用这些特性(步骤指南)

· 它们在 Android 和 iOS 上的适用性

· 如何为不同平台设置编译器标志

为 Android 和 iOS 设置编译器标志

在深入探讨具体的安全特性之前,我们先简要回顾一下如何在 Android 和 iOS 上设置这些编译器标志。如果您已经熟悉这些操作,可以跳过这一部分!

Android

通常,Android 应用的原生代码通过 ndk-build 脚本或结合 Gradle 使用 CMake 进行编译。在 ndk-build 的情况下,可以通过在 Application.mk 文件中添加新的标志来启用:

如果您使用的是 Gradle 配合 CMake,则可以在 build.gradle 文件中添加编译器标志:

iOS

在 iOS 中,您可以通过 Xcode 项目的“Build Settings”选项卡来设置编译器标志:

1. 在“Project Navigator”中选择您的项目文件。

2. 转到目标的“Build Settings”选项卡。

3. 在“Other C Flags”或“Other C++ Flags”部分添加所需的标志。

编译器相关的安全特性

1. 栈保护(Stack Canaries)

栈保护是一种防御缓冲区溢出攻击的基础技术。缓冲区溢出攻击发生时,攻击者通过溢出栈上的缓冲区,可能会覆盖函数的返回地址,从而执行任意代码,造成严重的安全漏洞,例如未经授权的访问或系统崩溃。启用栈保护(通过 -fstack-protector-strong 编译器标志)可以有效避免这类攻击。

· 适用于 Android: ✅

· 适用于 iOS: ✅

如果您想进一步了解该主题,可以查阅 Wikipedia 上关于缓冲区溢出保护的文章,或者阅读经典的《Smashing The Stack For Fun And Profit》一文。

2. 指针认证(Pointer Authentication,PAC)

指针认证(PAC)通过加密签名指针,尤其是返回地址和函数指针,以防止控制流攻击。若指针被篡改,验证失败,攻击将被阻止。这个特性依赖于特定的硬件支持,这可能会使设备的兼容性成为问题。但幸运的是,目前所有支持的 iOS 设备都已支持 PAC,而 Android 编译器会确保只使用在旧设备上不执行任何操作的指令。

· 适用于 Android: ✅

· 适用于 iOS: ✅

如何在 Android 上启用 PAC:

· 使用 ndk-build 时:在每个 Android.mk 文件中设置 LOCAL_BRANCH_PROTECTION := standard

· 使用 Gradle 配合 CMake 时:添加 -mbranch-protection=standard 编译器标志

在 PAC 的基础上,Google 还建议启用控制流完整性(CFI)。您可以在 LLVM 的官方网站上了解更多关于 CFI 的信息。

如何在 iOS 上启用 PAC:

在 Xcode 的构建设置中,将 arm64e 目标添加到“Architectures”部分。由于 Apple 控制硬件和软件,它可以为所有设备提供一致的 PAC 实施,而 Android 平台则需要根据设备硬件特性通过编译器标志来启用 PAC。

更多信息可以参考 Apple 的文章,了解如何为应用启用指针认证。

3. 只读重定位(Relocation Read-Only,RelRO)

RelRO 是一种保护应用免受内存篡改攻击的机制。它通过在初始化完成后将某些内存区域标记为只读来工作。特别是,它可以保护全局偏移表(GOT),该表用于管理应用程序中的动态链接函数。通过将 GOT 和其他关键区域标记为只读,RelRO 可以防止攻击者修改这些指针,从而劫持应用程序的执行流。

· 适用于 Android: ✅

· 适用于 iOS: ❌(iOS 没有 GOT 结构)

RedHat 博客有一篇很好的文章,详细介绍了 RelRO 的更多信息。

确保您的移动应用安全

确保您的应用安全不仅仅是编写安全代码,还需要采取综合措施,包括加强原生代码的构建过程。启用上述提到的编译器标志可以帮助您实现这一目标,降低常见攻击带来的风险,而且不会对性能造成显著影响。然而,建立安全的构建过程并不是一次性的任务,它需要持续的监控。在应用程序不断演进的过程中,确保这些安全配置始终保持有效非常重要。通过将 MAST(移动应用安全测试)工具集成到 CI 流水线中,您可以自动化地测试最终产品的安全性,捕捉构建设置中的回归问题,避免将不安全的应用发布给用户。


http://www.ppmy.cn/server/150978.html

相关文章

Java学习Day08——泛型

1. 泛型的理解和好处 1.1 使用传统方法的问题 1. 不能对加入到集合 ArrayList中的数据类型进行约束(不安全) 2. 遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响 1.2 泛型的好处 1. 编译时,检查添加元素的类型&…

如何使用 uni-app 构建直播应用程序?

使用uni-app构建直播应用程序涉及前端和后端的开发,以及音视频处理技术的选择。下面我将概述一个典型的直播应用架构,并详细说明如何在uni-app中实现关键功能。 直播应用架构 前端(uni-app):负责用户界面展示、互动逻…

240004基于Jamva+ssm+maven+mysql的房屋租赁系统的设计与实现

基于ssmmavenmysql的房屋租赁系统的设计与实现 1.项目描述2.运行环境3.项目截图4.源码获取 1.项目描述 该项目在原有的基础上进行了优化,包括新增了注册功能,房屋模糊查询功能,管理员和用户信息管理等功能,以及对网站界面进行了优…

Spring Security前置内容+关键内部类

目录 前置内容认证与授权配置和配置类 security内部的关键类UserDetailsUserUserDetailsService(加载用户数据,提供用户信息) 前置内容 认证与授权 认证即系统判断用户的身份是否合法,合法可继续访问,不合法则拒绝访…

vue2中echarts

如图示&#xff1a; 第一个&#xff1a; <div ref"charts" style"width:100%;height:99px;"></div> import * as echarts from echarts;mounted() {this.drawLine();},methods: {drawLine() {// 基于准备好的dom&#xff0c;初始化echarts实例…

代码随想录算法训练营第一天 | 数组理论基础,977.有序数组平方结果再排序

题目说明&#xff1a;数组本身有序&#xff0c;且元素值可通用负数&#xff08;注意不是复数&#xff09;&#xff0c;平方结果值还能以有序方式排列 标准想法就是在原数组基础上&#xff0c;把所有元素求平方结果值 再将这个有新结果值的数组&#xff0c;进行排序 生成平方…

操作系统(11)程序处理

前言 操作系统&#xff08;OS&#xff09;是管理计算机硬件与软件资源的计算机程序&#xff0c;它在计算机系统中扮演着至关重要的角色。 一、操作系统的作用 操作系统是直接运行在计算机上的系统软件&#xff0c;具有承上启下的作用。它向下控制硬件&#xff0c;向上支持软件的…

【从零开始入门unity游戏开发之——C#篇05】转义字符、@处理多行文本或者不使用转义字符、随机数

文章目录 一、转义字符1、什么是转义字符&#xff1f;2、常见的转义字符3、总结 二、使用处理多行文本或者不使用转义字符1、多行字符串2、不使用转义字符 三、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSin…