我正在努力提高代码安全性。我们使用名为CheckMarx的静态代码分析工具。该工具是公司的新工具,特别是我们是唯一一个使用目标C在iOS上工作的团队。
我有一个连接服务器的参数类,它包含服务器地址,端口,几个参数,登录名和密码 密码不应由用户录制,但是。每次需要时,它都会从另一个强身份验证服务中检索为令牌。它不应该保存为持久值(因为它每次都会改变),所以keychain看起来不能满足我的需要。 对于演示项目,用户将在textField中点击它。该演示项目正在进行安全验证。
运行分析时,我会进行堆检查'漏洞: 关于密码的https://cwe.mitre.org/data/definitions/244.html。理论上我理解我应该清除存储密码的内存空间的问题,但我不知道在目标C中实现这一点。
密码是一个NSString,它是不可变的,所以如果我试图覆盖NSString,我只会创建一个新的字符串,让旧的字符串放在堆中的某个地方。 (如果我在dealloc方法中覆盖它,我会得到另一个警告,说硬编码字符串对密码来说是一种不好的做法)。 将变量重命名为另一个虚拟变量名称,如MyDummyPropThatContainsData
1)ARC将清除指针,但我认为它不会清理堆。所以我相信这不是误报。我错了吗?
2)我尝试使用MAX_SIZE_PASSWORD分配的NSMutableString。我使用setString方法设置变量(在同一个地方)。我在dealloc方法中通过调用setString方法将其删除,其伪值恰好为MAX_SIZE_PASSWORD。它删除了警告,这是一个好习惯吗? 我很确定这应该是另一个警告说硬编码字符串是密码的坏习惯,但是没有检测到。我认为不好的做法仍然存在......
3)我曾经想过使用一个char *所以我以后可以记住它,但这对我来说听起来不好。我担心这可能是一个可靠性和维护问题。这可以解决我的问题吗?我是否建议使用ARC管理自己在我需要管理密码的地方分配char *?
我在目标C中没有发现任何可以防止堆检测漏洞的内容。在目标C中是否有一些常见的方法可以防止这种情况? 你知道从哪里开始的好点吗?
任何帮助表示赞赏!
答案 0 :(得分:4)
一条评论和一个食谱。在支持无交换或加密交换的系统中,对数据进行数据处理大多没有实际意义。发现密码的主要剩余攻击是直接附加到正在运行的应用程序。我使用钥匙串模式来抵御这种攻击。
目标是清除堆上的秘密。
当我将密码保存在我的钥匙串中时,它们将作为NSData
BLOB返回。这是关键。然后,您可以使用BLOB的字节初始化NSString
,并禁止字符串拥有它们(freeWhenDone: NO
)。虽然我无法保证NSString
不会复制数据,但似乎是这种情况。 (确保您没有指定导致NSString必须重新传输数据的编码.UTF-8通常可以正常工作。)
完成密码NSString
后,请将其释放。 (使用ARC,将其设置为nil。)
现在清理堆的关键是使用NSData
例程枚举每个字节数组,通常只有一个,然后将字节设置为NULL
。如果你愿意,你可以用随机字节敲打。您现在可以释放NSData
BLOB。
是的,这打破了可变性保存的所有规则。这就是不安全的指针操作。他们不安全。但是你也有充分的理由在特定的地方做某事。
由于这是一个相当精细的操作,我不愿意共享实现上述算法的代码。 IMO,您需要对自己的安全卫生负责。
如果上述情况不明确,我很乐意进一步完善答案。