java代码审计之反序列化(敏感信息泄露)
阅读原文时间:2021年04月20日阅读:1

前言

在 Java 环境中,允许处于不同受信域的组件进行数据通信,从而出现跨受信边界的数据传输。不要序列
化未加密的敏感数据;不要允许序列化绕过安全管理器。

public class GPSLocation implements Serializable
{
private double x; // sensitive field
private double y; // sensitive field
private String id;// non-sensitive field
// other content}
public class Coordinates
{
public static void main(String[] args)
{
FileOutputStream fout = null;
try
{
GPSLocation p = new GPSLocation(5, 2, "northeast");
fout = new FileOutputStream("location.ser");
ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(p);
oout.close();
}
catch (Throwable t)
{
// Forward to handler
}
finally
{
if (fout != null)
{
try
{
fout.close();
}
catch (IOException x)
{
// handle error
}}}}}

在这段示例代码中,假定坐标信息是敏感的,那么将其序列化到数据流中使之面临敏感信息泄露与被恶意
篡改的风险。

审计策略

要根据实际业务场景定义敏感数据。对于已经被确定为敏感的数据搜索示例一中相关的关键字。
修复方案
上面漏洞示例中的正确写法如下

public class GPSLocation implements Serializable
{
private transient double x; // transient field will not be serialized
private transient double y; // transient field will not be serialized
private String id;
// other content
}

要根据实际情况修复。 一般情况下,一旦定位,修复方法是将相关敏感数据声明为 transient,这样程
序保证敏感数据从序列化格式中忽略的。

正确示例( serialPersistentFields ) :

public class GPSLocation implements Serializable
{
private double x;
private double y;
private String id;// sensitive fields x and y are not content in serialPersistentFields
private static final ObjectStreamField[] serialPersistentFields = {new
ObjectStreamField("id", String.class)};
// other content
}

该示例通过定义 serialPersistentFields 数组字段来确保敏感字段被排除在序列化之外,除了上述方
案,也可以通过自定义 writeObject()、 writeReplace()、 writeExternal()这些函数,不将包含
敏感信息的字段写到序列化字节流中。特殊情况下,正确加密了的敏感数据可以被序列化。