Fortify 5.1漏洞整改方案(1)

    很多企业对代码的安全性有着很高的要求,目前使用的较为多的扫描代码安全漏洞的工具为Fortify 5.1。以下为一些漏洞的解决方案,欢迎指正。

1.Password Management: Empty Password

1)简介:为密码变量指定空字符串绝非一个好方法。如果使用 empty password 成功通过其他系统的验证,那么相应帐户的安全性很可能会被减弱,原因是其接受了 empty password。如果在为变量指定一个合法的值之前,empty password 仅仅是一个占位符,那么它将给任何不熟悉代码的人造成困惑,而且还可能导致出现意外控制流路径方面的问题。

 

例 1: 以下代码尝试使用empty password 连接数据库。

    ...

    DriverManager.getConnection(url, ""scott"", """");

...

 

如果例 1 中的代码成功执行,则表明数据库用户帐户“scott”配置了一个 empty password,攻击者可以轻松地猜测到这一点。更危险的是,程序一旦发布,更新帐户以使用非 empty password 时,需要对代码进行更改。

 

例 2: 以下代码可将密码变量初始化为空字符串,并尝试在存储的值中读取密码,且将其与用户提供的值进行比较。

    ...

    String storedPassword = """";

    String temp;

 

    if ((temp = readPassword()) != null) {

        storedPassword = temp;

    }

 

    if(storedPassword.equals(userPassword))

        // Access protected resources

        ...

    }

    ...

 

如果 readPassword() 因数据库错误或其他问题而未能取得存储的密码,攻击者只需向 userPassword 提供一个空字符串,就能轻松绕过密码检查。

 

在移动世界中,由于设备丢失的几率较高,因此密码管理是一个非常棘手的问题。

例 3:以下代码可将用户名和密码变量初始化为空字符串,如果服务器之前未拒绝这些变量当前提出的请求,代码就可从 Android WebView 存储读取凭证,并使用用户名和密码设置身份验证,从而查看受保护页面。

...

webview.setWebViewClient(new WebViewClient() {

  public void onReceivedHttpAuthRequest(WebView view,

        HttpAuthHandler handler, String host, String realm) {

    String username = """";

    String password = """";

 

    if (handler.useHttpAuthUsernamePassword()) {

      String[] credentials = view.getHttpAuthUsernamePassword(host, realm);

      username = credentials[0];

      password = credentials[1];

    }

    handler.proceed(username, password);

  }

});

...

与例 2 相似,如果 useHttpAuthUsernamePassword() 返回 false,攻击者就可以通过提供 empty password 查看受保护页面。

 

2)解决方案:由于该漏洞是根据password的关键字扫描出的结果,所以规避该类问题,最好的办法就是不使用password当变量。

修改前:

String password = "";

     try {

    password = AESUtils.encryptForJS(rawPassword);

     } catch (Exception e1) {

        logger.error(e1);

     }

修改后:

String pwd= "";

     try {

    pwd= AESUtils.encryptForJS(rawPassword);

     } catch (Exception e1) {

        logger.error(e1);

     }

 

2.Unreleased Resource: Sockets

1)简介:程序可能无法释放某个套接字。资源泄露至少有两种常见的原因:

- 错误状况及其他异常情况。

- 未明确程序的哪一部份负责释放资源。

 

大部分 Unreleased Resource 问题只会导致一般的软件可靠性问题,但如果攻击者能够故意触发资源泄漏,该攻击者就有可能通过耗尽资源池的方式发起 denial of service 攻击。

 

例 1:下面的方法绝不会关闭它所打开的套接字。在繁忙的环境中,这会导致 JVM 用尽它所有的套接字。

 

private void echoSocket(String host, int port) throws UnknownHostException, SocketException, IOException

{

  Socket sock = new Socket(host, port);

  BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));

 

  while ((String socketData = reader.readLine()) != null) {     System.out.println(socketData);   } }

 

例 2:正常情况下,以下修复代码会正常关闭套接字以及任何相关联的数据流。但如果在读取输入或将数据输出到屏幕时出现异常,则不会关闭套接字对象。如果这种情况经常出现,系统将会耗尽所有套接字,无法处理更多连接。

 

private void echoSocket(String host, int port) throws UnknownHostException, SocketException, IOException

{

  Socket sock = new Socket(host, port);

  BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));

 

  while ((String socketData = reader.readLine()) != null) {     System.out.println(socketData);   }   sock.close(); }

2)解决方案:释放资源。

修改前:

private ClientHandle getClientHandle() throws IOException,

InterruptedException {

Socket socket = null;

for (int retry = 4; retry-- != 0;)

try {

socket = new Socket(ip, port);

break;

} catch (Exception exception) {

Thread.sleep(10L);

}

if (socket == null) {

throw new InterruptedException("������æ!");

} else {

ClientHandle handle = new ClientHandle(socket);

return handle;

}

}

修改后:

private ClientHandle getClientHandle() throws IOException,

InterruptedException {

Socket socket = null;

for (int retry = 4; retry-- != 0;)

try {

socket = new Socket(ip, port);

break;

} catch (Exception exception) {

Thread.sleep(10L);

}

if (socket == null) {

throw new InterruptedException("������æ!");

} else {

ClientHandle handle = null;

try {

handle = new ClientHandle(socket);

} catch (Exception e) {

e.printStackTrace();

} finally {

if(socket != null) {

socket.close();

}

  }

return handle;

}

}

3.Null Dereference

1)简介:当违反程序员的一个或多个假设时,通常会出现 null 指针异常。如果程序明确将对象设置为 null,但稍后却间接引用该对象,则将出现 dereference-after-store 错误。此错误通常是因为程序员在声明变量时将变量初始化为 null。

大部分空指针问题只会引起一般的软件可靠性问题,但如果攻击者能够故意触发空指针间接引用,攻击者就有可能利用引发的异常绕过安全逻辑,或致使应用程序泄漏调试信息,这些信息对于规划随后的攻击十分有用。

示例:在下列代码中,程序员将变量 foo 明确设置为 null。稍后,程序员间接引用 foo,而未检查对象是否为 null 值。

Foo foo = null;

...

foo.setBar(val);

...

}

2)解决方案:使用对象前,需要进行判空。

 

修改前:

if (uploadFolder.startsWith(File.separator))

uploadFolder.replaceFirst(File.separator, "");

修改后:

if (uploadFolder!=null&&uploadFolder.startsWith(File.separator))

uploadFolder.replaceFirst(File.separator, "");

 

4.Insecure Randomness

1)简介:在对安全性要求较高的环境中,使用一个能产生可预测数值的函数作为随机数据源,会产生 Insecure Randomness 错误。

电脑是一种具有确定性的机器,因此不可能产生真正的随机性。伪随机数生成器 (PRNG) 近似于随机算法,始于一个能计算后续数值的种子。

PRNG 包括两种类型:统计学的 PRNG 和密码学的 PRNG。统计学的 PRNG 可提供有用的统计资料,但其输出结果很容易预测,因此数据流容易复制。若安全性取决于生成数值的不可预测性,则此类型不适用。密码学的 PRNG 通过可产生较难预测的输出结果来应对这一问题。为了使加密数值更为安全,必须使攻击者根本无法、或极不可能将它与真实的随机数加以区分。通常情况下,如果并未声明 PRNG 算法带有加密保护,那么它有可能就是一个统计学的 PRNG,不应在对安全性要求较高的环境中使用,其中随着它的使用可能会导致严重的漏洞(如易于猜测的密码、可预测的加密密钥、会话劫持攻击和 DNS 欺骗)。

示例: 下面的代码可利用统计学的 PRNG 为购买产品后仍在有效期内的收据创建一个 URL。

String GenerateReceiptURL(String baseUrl) {

    Random ranGen = new Random();

    ranGen.setSeed((new Date()).getTime());

    return (baseUrl + ranGen.nextInt(400000000) + "".html"");

}

这段代码使用 Random.nextInt() 函数为它所生成的收据页面生成独特的标识符。因为 Random.nextInt() 是一个统计学的 PRNG,攻击者很容易猜到由它所生成的字符串。尽管收据系统的底层设计也存在错误,但如果使用了一个不生成可预测收据标识符的随机数生成器(如密码学的 PRNG),会更安全一些。

2)解决方案:修改获取随机数的方式。

修改前:

Random r = new Random();

i = r.nextInt(15);

修改后:

SecureRandom s = new SecureRandom();

i= s.nextInt(15);

5.XML External Entity Injection

1)简介:XML External Entities 攻击可利用能够在处理时动态构建文档的 XML 功能。XML 实体可动态包含来自给定资源的数据。外部实体允许 XML 文档包含来自外部 URI 的数据。除非另行配置,否则外部实体会迫使 XML 解析器访问由 URI 指定的资源,例如位于本地计算机或远程系统上的某个文件。这一行为会将应用程序暴露给 XML External Entity (XXE) 攻击,从而用于拒绝本地系统的服务,获取对本地计算机上文件未经授权的访问权限,扫描远程计算机,并拒绝远程系统的服务。

下面的 XML 文档介绍了 XXE 攻击的示例。

 

 

  

  ]>&xxe;

 

如果 XML 解析器尝试使用 /dev/random 文件中的内容来替代实体,则此示例会使服务器(使用 UNIX 系统)崩溃。

2)解决方案:应对 XML 解析器进行安全配置,使它不允许将外部实体包含在传入的 XML 文档中。

为了避免 XXE injections,应为 XML 代理、解析器或读取器设置下面的属性:

factory.setFeature(""http://xml.org/sax/features/external-general-entities"", false);

factory.setFeature(""http://xml.org/sax/features/external-parameter-entities"", false);

如果不需要 inline DOCTYPE 声明,可使用以下属性将其完全禁用:

factory.setFeature(""http://apache.org/xml/features/disallow-doctype-decl"", true);

要保护 TransformerFactory,应设置下列属性:

  TransformerFactory transFact = TransformerFactory.newInstance();

  transFact.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, """");

  Transformer trans = transFact.newTransformer(xsltSource);

  trans.transform(xmlSource, result);

 

修改前:

TransformerFactory tFac = TransformerFactory.newInstance();

Transformer t = tFac.newTransformer(xslSource);

修改后:

TransformerFactory tFac = TransformerFactory.newInstance();

tFac.setFeature("http://xml.org/sax/features/external-general-entities", false);

tFac.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

Transformer t = tFac.newTransformer(xslSource);

 

6.Unreleased Resource: Streams

1)简介:"程序可能无法成功释放某一项系统资源。资源泄露至少有两种常见的原因:

- 错误状况及其他异常情况。

- 未明确程序的哪一部份负责释放资源。

大部分 Unreleased Resource 问题只会导致一般的软件可靠性问题,但如果攻击者能够故意触发资源泄漏,该攻击者就有可能通过耗尽资源池的方式发起 denial of service 攻击。

示例:下面的方法绝不会关闭它所打开的文件句柄。FileInputStream 中的 finalize() 方法最终会调用 close(),但是不能确定何时会调用 finalize() 方法。在繁忙的环境中,这会导致 JVM 用尽它所有的文件句柄。

 

private void processFile(String fName) throws FileNotFoundException, IOException {

  FileInputStream fis = new FileInputStream(fName);

  int sz;

  byte[] byteArray = new byte[BLOCK_SIZE];

  while ((sz = fis.read(byteArray)) != -1) {

    processBytes(byteArray, sz);

  }

}

2)解决方案:及时释放资源。

修改前:

OutputStream out = null;

try {

out = new FileOutputStream(outputZipFileName);

out.write(b);

} catch (Exception e) {

log.error(e);

}

修改后:

OutputStream out = null;

try {

out = new FileOutputStream(outputZipFileName);

out.write(b);

} catch (Exception e) {

log.error(e);

} finally {

if(out != null) {

//out.flush();

out.close();

}

}

 

8.Portability Flaw: Locale Dependent Comparison

1)简介:对可能与区域设置相关的数据进行比较时,应指定相应的区域设置。

示例 1:以下示例尝试执行验证,以确定用户输入是否包含

你可能感兴趣的:(Fortify 5.1漏洞整改方案(1))