Skip to content

Composite Format String

Composite format strings should not lead to unexpected behavior at runtime

What does this mean ?

Because composite format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that lead to unexpected behaviors or runtime errors.

What can happen ?

Run time errors are likely to come.

Sample Code

Vulnerable :

s = string.Format("[0}", arg0);
s = string.Format("{{0}", arg0);
s = string.Format("{0}}", arg0);
s = string.Format("{-1}", arg0);
s = string.Format("{0} {1}", arg0);

Non Vulnerable :

s = string.Format("{0}", 42); // Compliant
s = string.Format("{0,10}", 42); // Compliant
s = string.Format("{0,-10}", 42); // Compliant
s = string.Format("{0:0000}", 42); // Compliant
s = string.Format("{2}-{0}-{1}", 1, 2, 3); // Compliant
s = string.Format("no format"); // Compliant

Vulnerable :

public class ResponseSplitting extends HttpServlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    Calendar expirationDate = new GregorianCalendar(2017, GregorianCalendar.SEPTEMBER, 1);
    // User provided value
    String cardSecurityCode = request.getParameter("cardSecurityCode");

    if (notValid(cardSecurityCode)) {

      /*
      * BAD: user provided value is included in the format string.
      * A malicious user could provide an extra format specifier, which causes an
      * exception to be thrown. Or they could provide a %1$tm or %1$te format specifier to
      * access the month or day of the expiration date.
      */
      System.out.format(cardSecurityCode +
                          " is not the right value. Hint: the card expires in %1$ty.",
                        expirationDate);
    }

  }
}

Non Vulnerable :

public class ResponseSplitting extends HttpServlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    Calendar expirationDate = new GregorianCalendar(2017, GregorianCalendar.SEPTEMBER, 1);
    // User provided value
    String cardSecurityCode = request.getParameter("cardSecurityCode");

    if (notValid(cardSecurityCode)) {

      // GOOD: %s is used to include the user-provided cardSecurityCode in the output
      System.out.format("%s is not the right value. Hint: the card expires in %2$ty.",
                        cardSecurityCode,
                        expirationDate);
    }

  }
}

References