个人信息: 姓名、 性别、 年龄、 身份证号码、 电话号码。
健康信息: 健康记录、 服药记录、 健康状况。
教育记录: 教育经历、 学习课程、 考试分数。
消费记录: 所购货物、 购买记录、 支付记录。
账户信息: 信用卡号、 社交账号、 支付记录。
隐私信息: 家庭成员、 个人照片、 个人行程。
商业秘密: 设计程序、 制作工艺、 战略规划、 商业模式。
客户信息: 客户基本信息、 消费记录、 订单信息、 商业合作和合同。
雇员信息: 雇员基本信息、 工资报酬。
需要注意的是, 上述只是一些常见的、 直观的敏感信息。 具体到你开发的信息系统, 到底什么样
的信息是敏感信息, 什么样的信息不是敏感信息, 还需要进一步分析和界定。
识别出敏感信息之后, 就要想办法保护这些信息了。 敏感信息的保护, 需要恰当的管理, 也需要适合的技术
敏感信息指的是未经授权不得泄漏的信息。 这个概念可以拆分为三部分:
在JDK中, 权限通过java.security.Permission接口来定义。 Permission接口定义权限的名称和操作。
比如, java.io.FilePermission把权限名定义为文件名, 把操作定义为:
read
write
execute
delete
readlink
其中, 权限的名称就是抽象了的敏感信息; 权限的操作就是对信息的处理。 如果把权限的名称和权限的操作结合起来, 就可以定义特定的权限了。 比如, 下面的例子就定义了对于文件目录“/home/myhome”的读操作
permission java.io.FilePermission “/home/myhome”, “read”;
在JDK中, 权限的主体通过java.security.Principal接口来定义。 Principal接口可以用来表述个人, 组织或者虚拟的账户。
比如, com.sun.security.auth.UnixPrincipal可以用来表述Unix的用户。
Principal com.sun.security.auth.UnixPrincipal “duke”
也就是说, 有了权限的定义和权限主体的定义, 我们就可以分配权限了。 下面的例子, 就是把对“/home/duke”的读写操作权限, 赋予给了Unix用户duke。
grant Principal com.sun.security.auth.UnixPrincipal “duke” {
permission java.io.FilePermission “/home/duke”, “read, write”;
}
更详细的内容, 权限管理策略文件的语法以及API的调用, 请参阅有关Java的规范。
现代信息系统资源, 一般都是多用户共享, 多应用共享, 跨边界合作的, 比如内存、 硬盘、 中央处理器和互联网。 而敏感信息是不能共享的, 如何在共享的资源内, 不留下敏感信息的踪迹?
这是一个让人头疼的问题。
比如说吧, 要使用敏感信息, 就要把敏感信息载入内存, 如果发生内存溢出
攻击, 攻击者就可以绕过权限管理, 获取或者修改敏感信息, 甚至可以修改对敏感信息的操作。
针对敏感信息的操作, 需要特殊的处理和特殊的技术。
敏感信息的无意识泄露是一种比较常见的敏感信息泄露事件。 比如说, 把敏感信息泄露在抛出异常里, 应用日志里, 或者序列化对象里。
比如说, 如果一个文件不存在, 一般的代码实现会倾向于抛出java.io.FileNotFoundException异常。 为了使异常信息更加直观, 我们常常把文件路径包含在异常的消息里, 或者记录在应用日志里
java.io.FileNotFoundException: /home/duke/.ssh was not found
这个异常信息有可能绕过权限管理, 传达给未授权用户。 这个信息里包含了三个重要的敏感信息:
当实现一个文件管理类时, 我们可能会习惯于面向对象的机制。 比如, 给定一个文件的路径, 代码就执行一定的读写操作。 至于该文件路径是什么, 包含什么内容, 是否有敏感信息, 都不在该类的考虑范围之内。
实现这个类时, 我们更可能倾向于使用直观友好的异常信息, 而不会意识到这些异常信息可能携带敏感数据, 导致敏感数据通过异常信息泄露。
这和我们一般的面向对象的编程习惯是不符合的, 这就要求我们特别小心。 从实现者的角度出发, 抛出的异常信息尽量做到不包含可能的敏感信息; 从调用者的角度出发, 截获的异常信息在传递到上层调用之前, 如果有必要, 需要做净化处理。 比如, 把上述的
java.io.FileNotFoundException转化成更普通的java.io.IOException。
java.io.IOException: An IOException was caught!
java.io.IOException: An IOException was caught!
at com.example.myapp.MyHTTPSerer.myMethod(MyHTTPSerer.java:250)
...
Caused by java.io.FileNotFoundException: /home/duke/.ssh was not found
at com.example.myapp.MyFileStream.open(MyFileStream.java:249)
这个异常堆栈的“Caused by”部分泄露了同样的敏感信息。 所以, 在做异常信息净化处理时,可能还需要避免传递捕获异常的堆栈。 特别是如果调用结果直接面向最终用户, 就应当尽量避免使用异常堆栈。 比如说, 在HTML页面中显示异常信息和异常堆栈, 就容易出问题。
在后面的文章中, 我们还会讨论敏感信息及时归零的话题。 这也是对于高度敏感信息的一种特殊处理方式。