Type something to search...
保护你的应用程序:避免api密钥被盗的5个关键策略

保护你的应用程序:避免api密钥被盗的5个关键策略

人工智能的淘金热正在如火如荼地进行中。

在淘金热中,坏人会偷走铲子。

一个致命的错误是常见的:将 ChatGPT API 密钥直接捆绑到您闪亮的新 AI 应用中。这使得 盗取您的密钥消耗您的额度累积高额账单 变得非常简单。

今天,我将解释一个基本的 安全法则:

不要在客户端存储 API 密钥。绝对不要。

我将演示两种技术,允许坏人访问您的 API 密钥,并向您展示如何避免同样的命运。

反编译您的应用

如果您在设备上存储 API 密钥,您可能会采用各种复杂程度来保护它们。我将详细介绍最流行的方法,并演示它们是多么容易被绕过。

原始字符串在代码中

这通常是工程师在变得安全意识强之前采取的第一种方法。当从 API 请求数据时,您会写类似这样的代码:

func callChatGPTAPI(prompt: String) async throws -> Data {
    let url = URL(string: "https://api.chatgpt.com")!
    var request = URLRequest(url: url)
    let apiKey = "12345678-90ab-cdef-1234-567890abcdef"
    request.addValue(apiKey, forHTTPHeaderField: "Authorization")
    return try await URLSession.shared.data(for: request).0
}

这段代码被编译并以 .app 包的形式交付给用户,包含所有可执行代码。

我之前写过关于如何轻松获取应用商店中任何应用的 .ipa 文件的文章,该文件包含这个 .app 包。这是恶意行为者窃取您密钥的第一步。

Image 2

如果您想轻松阅读,可以查看 通过反编译他们的应用包在面试中给人留下深刻印象

通过这种方法,查看 .app 包内部是微不足道的。它只是一个文件夹,看起来像这样。

Image 3

真正的重点在于 Bev,这是 我值得信赖的酒精副项目 的 UNIX 可执行文件。它包含了我应用的所有 编译和链接代码

使用内置的 UNIX 命令 strings,我们可以检查这个编译的可执行文件中每个原始字符串。

自然,输出非常冗长:

Image 4

除了原始字符串,您还会看到许多编译函数的符号名称。

但在这个列表的底部,我们看到了我们的奖品:

12345678-90ab-cdef-1234-567890abcdef

我们的 API 密钥的原始字符串,暴露在外——任何精通正则表达式的人都可以轻松搜索到。

Info.plist

你可能会想,好吧,我不会把原始字符串放入我的应用程序中,以便它们可以被轻易反编译。

所以我会把它们放在 Info.plist 中,这是它们_应该_在的地方。

你的 API 调用位置变得有点复杂,以获取这个值。

func callChatGPTAPI(prompt: String) async throws -> Data {
    let url = URL(string: "https://api.chatgpt.com")!
    var request = URLRequest(url: url)
    let apiKey = getAPIKeyPlist()
    request.addValue(apiKey, forHTTPHeaderField: "Authorization")
    return try await URLSession.shared.data(for: request).0
}

func getAPIKeyPlist() -> String? {
    Bundle.main.object(forInfoDictionaryKey: "API_KEY") as? String
}

这里有几个复杂的子层级。与其直接硬编码密钥,你可能有多个密钥集,用于开发和生产。你可以为每个环境创建 .xcconfig 文件,这些文件在构建时解析为 Info.plist 中的值。

如果你是一个安全狂热者,你会知道绝不能将秘密提交到源代码控制中。更进一步,也许你会在你的 CI/CD 管道中安全地存储你的 API 密钥,将它们注入到 .xcconfigInfo.plist 中,作为构建脚本的一部分。

但这一切都是徒劳的。

因为让我们再看看那个反编译的应用程序,任何拥有 MacBook、iPhone 和过多闲暇时间的人都可以获取:

糟糕。

无论它们是如何到达那里的,放入 Info.plist 中的值都是公开可用的。

混淆字符串

如果你不加批判地听信你在互联网上阅读的所有内容,你可能会认为通过混淆你的字符串来保护自己是很聪明的。2019年我第一次决定成为常驻安全专家时,我确实是这么想的。

你可以对你的混淆算法和加盐做得非常复杂,但实际上,你会让 ChatGPT 为你编写一对函数,以混淆和解码你的 API 密钥。

private func obfuscate(key: String) -> String? {
    let salt = "00000000-0000-0000-0000-000000000000"
    guard let keyData = key.data(using: .utf8),
          let saltData = salt.data(using: .utf8) else {
        return nil
    }
    let obfuscatedData = zip(keyData, saltData).map { $0 ^ $1 }
    let obfuscatedBase64 = Data(obfuscatedData).base64EncodedString()
    return obfuscatedBase64
}

private func decode(obfuscated: String) -> String? {
    let salt = "00000000-0000-0000-0000-000000000000"
    guard let obfuscatedData = Data(base64Encoded: obfuscated),
          let saltData = salt.data(using: .utf8) else {
        return nil
    }
    let apiKeyData = zip(obfuscatedData, saltData).map { $0 ^ $1 }
    return String(bytes: apiKeyData, encoding: .utf8)
}

在运行时获取密钥就像解码原始混淆字符串一样简单。

func callChatGPTAPI(prompt: String) async throws -> Data {    
    let url = URL(string: "https://api.chatgpt.com")!
    var request = URLRequest(url: url)
    let apiKey = getAPIKeyObfuscated()
    request.addValue(apiKey, forHTTPHeaderField: "Authorization")
    return try await URLSession.shared.data(for: request).0
}

func getAPIKeyObfuscated() -> String? {
    decode(obfuscated: "AQIDBAUGBwgACQBRUgBTVFVWAAECAwQABQYHCAkAUVJTVFVW")
}

虽然这比原始字符串稍微难以阅读,但对于一个足够有动机的黑客来说,窃取你的密钥仍然很简单。

如果你使用不安全的方法,例如 base-64 编码或异或,逆向工程是微不足道的。即使有一个不错的算法和盐,攻击者也可以使用像Frida这样的工具在运行时从设备内存中提取你的 API 密钥。

混淆提供了_模糊带来的安全性_,但这并不是一个有效的方法。无论你的混淆多么优秀,那个 API 密钥最终都必须被解码并在某个时刻发送到 API。

这引出了我们最后也是最简单的窃取 API 密钥的方法。

监控网络流量

这是您可以使用的最强大技术之一。

像 Proxyman(或者如果您是老玩家,可以使用 Charles 代理)这样的免费工具允许您检查应用程序或网站的所有进出流量。

在加载程序的几秒钟内,我们立即在网络请求中发现包含我们 API 密钥的授权头。

12345678-90ab-cdef-1234-567890abcdef

因为我很奇怪,这就是我在开始新工作之前喜欢做的 另一件事:检查一些网络流量,以找出他们是 REST 还是 GraphQL。

减轻代理攻击

可以使用 SSL 钉扎等技术来减轻这种攻击向量。SSL 钉扎检查后端服务器提供的 TLS 证书,以确保它们与存储在设备上的证书匹配。这可以防止中间人攻击,并阻止网络代理工具的代理根证书。

要在 iOS 上实现 SSL 钉扎,可以创建一个使用 URLSessionDelegate 的网络请求装饰器,该装饰器实现 urlSession(didReceive: URLAuthenticationChallenge)

但是,你猜对了,SSL 钉扎并不一定如人们所想的那样完美。反编译者可以使用工具来绕过钉扎,尤其是在使用越狱设备时。

此外,当你不知道自己在做什么时,SSL 钉扎可能会带来风险。

当我还是一名相对初级的工程师,急于证明自己时,我天真地使用 AWS 拥有的 EC2 根证书实现了 SSL 钉扎。自然,AWS 在同一周轮换了证书。长话短说,英国的 COVID-19 测试中心在我生命中最长的 59 分钟内变得无法使用。

我应该做什么?

我希望到现在为止,你已经内化了我们的主要教训:保护客户端 API 密钥在很大程度上是安全表演。如果你将 API 密钥打包到公开分发的应用程序中,它们将永远不会安全。

既然我们知道了不该做什么,我们能做什么呢?

虽然客户端本质上不安全,但保护你的后端免受恶意行为者的攻击要简单得多。保护第三方 API 密钥的“教科书”方法是将它们放在一个(轮换的)秘密管理器中,并通过你的后端代理网络请求。

通过这种方法,你可以使用自己的系统对网络请求进行身份验证,并最小化潜在的攻击向量。

如果你还没有完全构建自己的基础设施,Firebase Cloud Functions 是实现这个中间件层的简单方法。

顺便提一下,你可以通过像 iOS 上的 AppAttestAndroid 上的 Play Integrity 和实施 RASP (运行时应用程序自我保护) 库 来为你的设备添加更多保护层。这些工具可以阻止你的应用在越狱设备上运行,并防止逆向工程工具的使用。

对我的建议的小补充:如果你正在使用 Firebase,我发现 AppAttest 存在很大的问题。也许他们已经修复了,但我从不放过抱怨的机会。

结论

不要在客户端存储 API 密钥。

就像,绝对 不要。

任何告诉你 API 密钥在客户端是安全的人,要么是愚蠢的,要么是恶意的。

任何打包到你的应用程序中的东西都可以被检查。原始字符串和 Info.plist 文件中的 API 密钥很容易被找到,而更复杂的混淆方法仍然容易受到有动机攻击者的攻击。

网络代理是一个强大的工具,既可以用于善,也可以用于恶。保护机制如 SSL 钉扎如果你不知道自己在做什么,可能会带来更多麻烦。客户端保护机制,如应用完整性检查或反编译检测库,有助于为你的应用或网站增加保护层。

如果你想合理地保护你的 API 密钥,你需要将所有内容存储在后端,或者使用 Firebase Cloud Functions 等产品。你可以安心睡觉,知道你的 API 密钥是安全的。可能是。

Jacob’s Tech Tavern 对于你在遵循我的建议后产生的 $5,000 ChatGPT 或 Firebase 账单不承担任何责任。

Related Posts

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

AI 研究报告和论文写作 合并两个系统指令以获得两个模型的最佳效果 Perplexity AI 的 Deep Research 工具提供专家级的研究报告,而 OpenAI 的 ChatGPT-o3-mini-high 擅长推理。我发现你可以将它们结合起来生成令人难以置信的论文,这些论文比任何一个模型单独撰写的都要好。你只需要将这个一次性提示复制到 **

阅读更多
让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

Non members click here作为一名软件开发人员,多年来的一个发现总是让我感到惊讶,那就是人们还在 Excel

阅读更多
使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

10 个常见问题解答 本文是我推出的一个名为“10 个常见问题解答”的新系列的一部分。在本系列中,我旨在通过回答关于该主题的十个最常见问题来分解复杂的概念。我的目标是使用简单的语言和相关的类比,使这些想法易于理解。 图片来自 [Solen Feyissa](https://unsplash.com/@solenfeyissa?utm_source=medium&utm_medi

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

在AI军备竞赛中分辨事实与虚构 DeepSeek AI真的是它所宣传的游戏规则改变者,还是仅仅聪明的营销和战略炒作?👀 虽然一些人将其视为AI效率的革命性飞跃,但另一些人则认为它的成功建立在借用(甚至窃取的)创新和可疑的做法之上。传言称,DeepSeek的首席执行官在疫情期间像囤积卫生纸一样囤积Nvidia芯片——这只是冰山一角。 从其声称的550万美元培训预算到使用Open

阅读更多
Type something to search...