简体中文

开发者工具 · Base64 编码器和解码器

Base64 不是加密:为什么任何人都可以读取编码的秘密

· 为什么它很重要

base64 安全 编码

Base64编码文本无需密钥即可立即解码,显示明文内容
原始 ToolAcre 矢量图

Base64 不隐藏任何内容:任何拥有该字符串的人都可以立即对其进行解码,无需密钥。这篇文章解释了编码、加密和散列之间的区别,以及当您在存储库中找到 Base64 机密时该怎么做。

看起来被扰乱并解码为数据库密码的配置值 - 一个具体的发现以及它反转的速度

在配置文件中查找 Base64 会产生错误的安全感。开发人员发现一个数据库密码,该密码显示为像 dGlnZXJfZGF0YWJhc2VfYWRtaW4 这样的加扰序列,假设它已加密,并将其与应用程序代码一起提交到存储库。几周后,安全审查揭示了实际的明文:tiger_database_admin。

Base64 不隐藏任何内容;它是一种编码,而不是加密。反转后的相同密码会立即在浏览器中再次变为原始密码,无需密钥、无需计算、无延迟。这篇文章解释了编码存在的原因、它与加密和散列的根本区别,以及当有人在提交的历史记录中发现 Base64 秘密时实际发生的情况。

编码、加密和散列:三种不同的工作——每项保证什么,以及哪一项需要密钥

之所以会产生混淆,是因为 Base64 看起来像是保护。人类无法看一眼 dGlnZXJfZGF0YWJhc2VfYWRtaW4 并读取 Tiger_database_admin。在通过解码器运行它之前,它看起来很模糊。这种表面级别的混淆感觉像是安全的,但事实并非如此。 Base64 旨在完全解决另一个问题:通过纯文本通道移动任意二进制数据。电子邮件、旧版 Web 表单和线路协议系统无法携带原始字节。 Base64 将字节转换为可打印的 ASCII 字符,以便数据可以完整地通过这些通道。

数据到达后,接收者将其解码回字节。编码和解码同样简单;它们不需要密钥,不需要熵,不需要密码库。编码、加密和散列服务于三个不同的目的并提供三种不同的保证。编码将数据转换为不同的表示形式,以便它可以通过特定的通道或在特定的上下文中使用。 Base64、URL 编码、十六进制表示,甚至 JSON 中的转义引号都是编码。任何人都可以逆转它们,并且不需要密钥。

为什么 Base64 存在——通过文本通道安全传输字节,而不是机密性

目标是格式兼容性,而不是机密性。相比之下,加密需要只有授权方知道的密钥。只有拥有正确密钥的人才能将密文恢复为明文。如果没有密钥,即使对于能够攻击它的老练的人来说,消息仍然是不透明的。哈希在设计上是单向的:密码的加密哈希根本无法逆转。它用于验证密码是否与存储的哈希值匹配,而不存储密码本身。

名为database-password 的 Kubernetes Secret 包含 base64: dGlnZXJfZGF0YWJhc2VfYWRtaW4 实际上并不是秘密。 Base64 是 Kubernetes 用于存储而非保护的默认编码。任何有权访问 YAML 或 etcd 数据库的人都可以在几秒钟内解码该值。启动脚本中具有 Base64 编码 API 密钥的环境变量也面临同样的问题。向服务器发送 Authorization: Basic base64_username:password 的 Basic Authentication 标头可以由客户端和服务器之间的任何代理、监控工具或网络观察器进行解码。

工作示例:在浏览器中解码“秘密”字符串 - 粘贴、解码和纯文本,不涉及服务器

如果通道是 HTTP 而不是 HTTPS,则暴露程度更大。在这些情况下,Base64 是一种转移注意力的方法:真正的秘密已经因以可恢复的形式存储或传输而受到损害。一个有效的例子使问题变得具体。假设第三方服务的 API 密钥在配置文件中显示为 YXBpa2V5XzEyMzQ1Njc4OTAx。将此字符串复制到浏览器中的 Base64 编码器和解码器中,将其粘贴到输入字段中,然后单击“解码”。

该工具返回 apikey_1234567890。这在您的浏览器中立即发生,无需联系服务器,无需密钥,也无需执行身份验证。整个操作过程不到一秒钟。现在假设恶意行为者在公共 GitHub 存储库中找到了相同的密钥。他们可以使用他们喜欢的任何工具同样轻松地对其进行解码,并使用它来访问服务。无论字符串在存储库中保持模糊、通过网络传播还是出现在应用程序日志中,都可以通过每种编程语言和像这样的浏览器工具中可用的简单操作来显示。

此错误出现的位置 — Kubernetes Secret、.env 文件、基本身份验证标头和移动应用程序资源

这个错误随处可见,因为 Base64 非常常见,以至于它与邻近混淆有关。开发人员看到 Base64 编码的数据,推断有人认为它很重要,并以这种形式留下秘密。对于初级工程师来说,包含 API_KEY=VGhpcyBpcyBub3QgcmVhbGx5IGEgc2VjcmV0 的 .env 文件比 API_KEY= 更安全,尽管解码需要一次操作,但这并不是真正的秘密。移动应用程序将 Base64 编码的令牌捆绑在任何反编译器都可以提取和解码的资源中。数据库备份在旨在搜索而非保护的字段中包含 Base64 编码的密码。

在每种情况下,都有人将编码误认为是加密,并创建了一个明文秘密档案,而该档案的格式恰好需要一个额外的步骤才能读取。发现 Base64 机密后该怎么做取决于上下文。

该怎么做 — 秘密管理器、真正的静态加密以及轮换任何已提交的内容

如果秘密是令牌、API 密钥或密码,并且已提交版本控制,则将其视为已泄露。撤销它,生成一个新的并更新它使用过的每个地方。历史提交是存储库永久记录的一部分,即使该秘密后来在新提交中被删除;任何有权访问存储库历史记录的人都可以找到它。

在存储库中搜索 Base64 编码的值现在是一种标准的侦察策略,因此某些东西是 Base64 的事实并不意味着它是秘密的。对于任何正在进行的操作,切勿使用 Base64 对机密进行编码并假设它们受到保护。使用秘密管理器来存储加密、访问控制和可审计的值。在应用程序代码和配置中仅存储引用或派生,而不存储秘密本身。真正的静态加密意味着数据使用单独存储的密钥进行加密,对于没有该密钥的任何人来说都是无用的。

这不包括什么 - 选择加密算法或密钥管理设计

加密敏感列的数据库、使用硬件安全模块中的密钥进行信封加密的机密管理器或从用户密码派生加密密钥的密码管理器都提供真正的机密性。在秘密被存储在任何地方之前创建的应用程序级加密更加强大。轮换已暴露的秘密,即使它们只是 Base64 编码,也可以消除滥用的机会。如果机密位于存储库中,请检查日志以查看其被访问的时间以及在暴露窗口期间的用途。

为了持续的安全性,请使用授权服务颁发的短期令牌,而不是存储在配置中的静态机密。即使受到威胁,一小时后过期的令牌对攻击者来说价值也会降低。本文不涉及选择加密算法、密钥管理设计或身份验证架构。这些都是更深层次的工程问题,有自己的标准和权衡。要点更简单:Base64 不是解决这些问题的工具之一。它是一种用于传输和存储的格式转换。

要点:将 Base64 视为明文 — Base64 编码器和解码器如何一键指出要点,而秘密永远不会离开您的选项卡

不要让存储库、配置文件或日志中出现 Base64 来安慰您数据受到保护。任何可以读取文本的工具都可以解码 Base64,并且操作是即时且确定的。将 Base64 编码的字符串读取为密文是一种常见的误解,它会暴露真正的秘密。开发人员通常只有在生产或审计中发现 Base64 秘密后才意识到这一点。当工程师在本地解码示例字符串并看到原始明文立即出现时,就会出现新的视角。

该工具使这一点不可避免:编码不是加密。一旦明确了区别,后续行动就会自动进行。代码库中的每个 Base64 密钥都必须进行轮换。每个使用秘密的地方都必须更新。必须评估暴露窗口。未来,秘密管理器和真正的加密必须取代编码这一角色。 Base64 编码器和解码器准确显示反转的速度和容易程度,您的秘密永远不会离开浏览器。将这种轻松视为实际的安全态势:如果您可以在一秒钟内解码它,那么其他人也可以。