/** * @name Information exposure through an exception * @description Leaking information about an exception, such as messages and stack traces, to an * external user can expose implementation details that are useful to an attacker for * developing a subsequent exploit. * @kind problem * @problem.severity error * @precision high * @id cs/information-exposure-through-exception * @tags security * external/cwe/cwe-209 * external/cwe/cwe-497 */ import csharp import semmle.code.csharp.frameworks.System import semmle.code.csharp.security.dataflow.XSS /** * A taint-tracking configuration for reasoning about stack traces that flow to web page outputs. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { this = "StackTrace" } override predicate isSource(DataFlow::Node source) { exists(Expr exceptionExpr | // Writing an exception directly is bad source.asExpr() = exceptionExpr or // Writing an exception property is bad source.asExpr().(PropertyAccess).getQualifier() = exceptionExpr or // Writing the result of ToString is bad source.asExpr() = any(MethodCall mc | mc.getQualifier() = exceptionExpr and mc.getTarget().hasName("ToString")) | // Expr has type `System.Exception`. exceptionExpr.getType().(RefType).getABaseType*() instanceof SystemExceptionClass and // And is not within an exception callable. not exists(Callable enclosingCallable | enclosingCallable = exceptionExpr.getEnclosingCallable() | enclosingCallable.getDeclaringType().getABaseType*() instanceof SystemExceptionClass ) ) } override predicate isSink(DataFlow::Node sink) { sink instanceof XSS::Sink } override predicate isSanitizer(DataFlow::Node sanitizer) { // Do not flow through Message sanitizer.asExpr() = any(SystemExceptionClass se).getProperty("Message").getAnAccess() } } from TaintTrackingConfiguration c, DataFlow::Node source, DataFlow::Node sink where c.hasFlow(source, sink) select sink, "Exception information from $@ flows to here, and is exposed to the user.", source, source.toString()