CodeQL queries 1.25
Skip to end of metadata
Go to start of metadata

Name: Uncontrolled format string

Description: Passing untrusted format strings from remote data sources can throw exceptions and cause a denial of service.

ID: cs/uncontrolled-format-string

Kind: path-problem

Severity: error

Precision: high

Query: UncontrolledFormatString.ql
/**
 * @name Uncontrolled format string
 * @description Passing untrusted format strings from remote data sources can throw exceptions
 *              and cause a denial of service.
 * @kind path-problem
 * @problem.severity error
 * @precision high
 * @id cs/uncontrolled-format-string
 * @tags security
 *       external/cwe/cwe-134
 */

import csharp
import semmle.code.csharp.security.dataflow.flowsources.Remote
import semmle.code.csharp.security.dataflow.flowsources.Local
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.frameworks.Format
import DataFlow::PathGraph

class FormatStringConfiguration extends TaintTracking::Configuration {
  FormatStringConfiguration() { this = "FormatStringConfiguration" }

  override predicate isSource(DataFlow::Node source) {
    source instanceof RemoteFlowSource
    or
    source instanceof LocalFlowSource
  }

  override predicate isSink(DataFlow::Node sink) {
    sink.asExpr() = any(FormatCall call).getFormatExpr()
  }
}

from FormatStringConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows to here and is used as a format string.",
  source.getNode(), source.getNode().toString()

Passing untrusted format strings to String.Format can throw exceptions and cause a denial of service. For example, if the format string references a missing argument, or an argument of the wrong type, then System.FormatException is thrown.

Recommendation

Use a string literal for the format string to prevent the possibility of data flow from an untrusted source. This also helps to prevent errors where the arguments to String.Format do not match the format string.

If the format string cannot be constant, ensure that it comes from a secure data source or is compiled into the source code.

Example

In this example, the format string is read from an HTTP request, which could cause the application to crash.

using System.Web;

public class HttpHandler : IHttpHandler
{
    string Surname, Forenames, FormattedName;

    public void ProcessRequest(HttpContext ctx)
    {
        string format = ctx.Request.QueryString["nameformat"];

        // BAD: Uncontrolled format string.
        FormattedName = string.Format(format, Surname, Forenames);
    }
}

References